diff --git a/Cargo.lock b/Cargo.lock index 20dfa90a39..cf90013a2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5479,6 +5479,7 @@ dependencies = [ "tailcall-prettier", "tailcall-tracker", "tailcall-typedefs-common", + "tailcall-valid", "tailcall-version", "tempfile", "test-log", @@ -5671,6 +5672,22 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tailcall-valid" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32dc2612dd67fdbe214cd396b388a386974d57daf732f00c2562b3b2421778d" +dependencies = [ + "derive_setters", + "http 1.1.0", + "regex", + "serde", + "serde_json", + "serde_path_to_error", + "thiserror", + "wasm-bindgen", +] + [[package]] name = "tailcall-version" version = "0.1.0" @@ -5690,6 +5707,7 @@ dependencies = [ "reqwest 0.11.27", "serde_json", "tailcall", + "tailcall-valid", "tracing", "tracing-subscriber", "tracing-subscriber-wasm", diff --git a/Cargo.toml b/Cargo.toml index 2c9ef63b53..2637e8110b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ derive_more = "0.99.18" thiserror = "1.0.59" url = { version = "2.5.0", features = ["serde"] } convert_case = "0.6.0" +tailcall-valid = "0.1.1" [dependencies] # dependencies specific to CLI must have optional = true and the dep should be added to default feature. @@ -169,6 +170,7 @@ num = "0.4.3" indenter = "0.3.3" derive_more = { workspace = true } strum = "0.26.2" +tailcall-valid = { workspace = true } dashmap = "6.1.0" urlencoding = "2.1.3" diff --git a/benches/handle_request_bench.rs b/benches/handle_request_bench.rs index 38c135c996..f33c52a895 100644 --- a/benches/handle_request_bench.rs +++ b/benches/handle_request_bench.rs @@ -7,7 +7,7 @@ use tailcall::core::async_graphql_hyper::GraphQLRequest; use tailcall::core::blueprint::Blueprint; use tailcall::core::config::{Config, ConfigModule}; use tailcall::core::http::handle_request; -use tailcall::core::valid::Validator; +use tailcall_valid::Validator; static QUERY: &str = r#"{"query":"query{posts{title}}"}"#; diff --git a/src/cli/generator/config.rs b/src/cli/generator/config.rs index 183ee15c2f..e2fba5aafd 100644 --- a/src/cli/generator/config.rs +++ b/src/cli/generator/config.rs @@ -7,12 +7,12 @@ use derive_setters::Setters; use path_clean::PathClean; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use tailcall_valid::{Valid, ValidateFrom, Validator}; use url::Url; use crate::core::config::transformer::Preset; use crate::core::config::{self}; use crate::core::http::Method; -use crate::core::valid::{Valid, ValidateFrom, Validator}; #[derive(Deserialize, Serialize, Debug, Default, Setters)] #[serde(rename_all = "camelCase")] @@ -268,9 +268,9 @@ mod tests { use std::collections::HashMap; use pretty_assertions::assert_eq; + use tailcall_valid::{ValidateInto, ValidationError, Validator}; use super::*; - use crate::core::valid::{ValidateInto, ValidationError, Validator}; fn location>(s: S) -> Location { Location(s.as_ref().to_string(), PhantomData) diff --git a/src/cli/generator/generator.rs b/src/cli/generator/generator.rs index 9120e3f62d..4cdbb1ea50 100644 --- a/src/cli/generator/generator.rs +++ b/src/cli/generator/generator.rs @@ -4,6 +4,7 @@ use std::path::Path; use http::header::{HeaderMap, HeaderName, HeaderValue}; use inquire::Confirm; use pathdiff::diff_paths; +use tailcall_valid::{ValidateInto, Validator}; use super::config::{Config, LLMConfig, Resolved, Source}; use super::source::ConfigSource; @@ -14,7 +15,6 @@ use crate::core::generator::{Generator as ConfigGenerator, Input}; use crate::core::proto_reader::ProtoReader; use crate::core::resource_reader::{Resource, ResourceReader}; use crate::core::runtime::TargetRuntime; -use crate::core::valid::{ValidateInto, Validator}; use crate::core::{Mustache, Transform}; /// CLI that reads the the config file and generates the required tailcall diff --git a/src/core/blueprint/auth.rs b/src/core/blueprint/auth.rs index 9ca378103a..55ab644626 100644 --- a/src/core/blueprint/auth.rs +++ b/src/core/blueprint/auth.rs @@ -2,9 +2,9 @@ use std::collections::HashSet; use std::fmt::Debug; use jsonwebtoken::jwk::JwkSet; +use tailcall_valid::Valid; use crate::core::config::ConfigModule; -use crate::core::valid::Valid; #[derive(Clone, Debug, PartialEq, Eq)] pub struct Basic { diff --git a/src/core/blueprint/cors.rs b/src/core/blueprint/cors.rs index 3173907734..b871d1905e 100644 --- a/src/core/blueprint/cors.rs +++ b/src/core/blueprint/cors.rs @@ -1,10 +1,12 @@ +use std::fmt::Display; + use derive_setters::Setters; use http::header; use http::header::{HeaderName, HeaderValue}; use http::request::Parts; +use tailcall_valid::ValidationError; use crate::core::config; -use crate::core::valid::ValidationError; #[derive(Clone, Debug, Setters, Default)] pub struct Cors { @@ -155,17 +157,26 @@ fn ensure_usable_cors_rules(layer: &Cors) -> Result<(), ValidationError> Ok(()) } +fn to_validation_err(err: T) -> ValidationError { + ValidationError::new(err.to_string()) +} + impl TryFrom for Cors { type Error = ValidationError; fn try_from(value: config::cors::Cors) -> Result> { let cors = Cors { allow_credentials: value.allow_credentials.unwrap_or_default(), - allow_headers: (!value.allow_headers.is_empty()) - .then_some(value.allow_headers.join(", ").parse()?), + allow_headers: (!value.allow_headers.is_empty()).then_some( + value + .allow_headers + .join(", ") + .parse() + .map_err(to_validation_err)?, + ), allow_methods: { Some(if value.allow_methods.is_empty() { - "*".parse()? + "*".parse().map_err(to_validation_err)? } else { value .allow_methods @@ -173,21 +184,28 @@ impl TryFrom for Cors { .map(|val| val.to_string()) .collect::>() .join(", ") - .parse()? + .parse() + .map_err(to_validation_err)? }) }, allow_origins: value .allow_origins .into_iter() - .map(|val| Ok(val.parse()?)) + .map(|val| val.parse().map_err(to_validation_err)) .collect::>>()?, allow_private_network: value.allow_private_network.unwrap_or_default(), - expose_headers: Some(value.expose_headers.join(", ").parse()?), + expose_headers: Some( + value + .expose_headers + .join(", ") + .parse() + .map_err(to_validation_err)?, + ), max_age: value.max_age.map(|val| val.into()), vary: value .vary .iter() - .map(|val| Ok(val.parse()?)) + .map(|val| val.parse().map_err(to_validation_err)) .collect::>>()?, }; ensure_usable_cors_rules(&cors)?; diff --git a/src/core/blueprint/definitions.rs b/src/core/blueprint/definitions.rs index eb47aad71d..15dc40bb41 100644 --- a/src/core/blueprint/definitions.rs +++ b/src/core/blueprint/definitions.rs @@ -4,6 +4,7 @@ use async_graphql_value::ConstValue; use directive::Directive; use interface_resolver::update_interface_resolver; use regex::Regex; +use tailcall_valid::{Valid, Validator}; use union_resolver::update_union_resolver; use crate::core::blueprint::*; @@ -11,7 +12,6 @@ use crate::core::config::{Config, Enum, Field, GraphQLOperationType, Protected, use crate::core::directive::DirectiveCodec; use crate::core::ir::model::{Cache, IR}; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, Validator}; use crate::core::{config, scalar, Type}; pub fn to_scalar_type_definition(name: &str) -> Valid { diff --git a/src/core/blueprint/directive.rs b/src/core/blueprint/directive.rs index 25c99a2395..3ef9045a3b 100644 --- a/src/core/blueprint/directive.rs +++ b/src/core/blueprint/directive.rs @@ -3,8 +3,8 @@ use std::collections::HashMap; use async_graphql::parser::types::ConstDirective; use async_graphql::Name; use serde_json::Value; +use tailcall_valid::{Valid, ValidationError, Validator}; -use crate::core::valid::{Valid, ValidationError, Validator}; use crate::core::{config, pos}; #[derive(Clone, Debug)] diff --git a/src/core/blueprint/from_config.rs b/src/core/blueprint/from_config.rs index 1617931591..e9a8d094b3 100644 --- a/src/core/blueprint/from_config.rs +++ b/src/core/blueprint/from_config.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use async_graphql::dynamic::SchemaBuilder; use indexmap::IndexMap; +use tailcall_valid::{Valid, ValidationError, Validator}; use self::telemetry::to_opentelemetry; use super::Server; @@ -12,7 +13,6 @@ use crate::core::config::{Arg, Batch, Config, ConfigModule}; use crate::core::ir::model::{IO, IR}; use crate::core::json::JsonSchema; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; use crate::core::Type; pub fn config_blueprint<'a>() -> TryFold<'a, ConfigModule, Blueprint, String> { diff --git a/src/core/blueprint/interface_resolver.rs b/src/core/blueprint/interface_resolver.rs index 83172f1a03..8fca58cbc5 100644 --- a/src/core/blueprint/interface_resolver.rs +++ b/src/core/blueprint/interface_resolver.rs @@ -1,11 +1,12 @@ use std::collections::BTreeSet; +use tailcall_valid::{Valid, Validator}; + use crate::core::blueprint::FieldDefinition; use crate::core::config::{ConfigModule, Discriminate, Field, Type}; use crate::core::ir::model::IR; use crate::core::ir::Discriminator; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, Validator}; fn compile_interface_resolver( interface_name: &str, diff --git a/src/core/blueprint/into_document.rs b/src/core/blueprint/into_document.rs index c468a82e1e..cf9f25c9cb 100644 --- a/src/core/blueprint/into_document.rs +++ b/src/core/blueprint/into_document.rs @@ -5,12 +5,12 @@ use async_graphql::parser::types::{ }; use async_graphql::{Name, Positioned}; use async_graphql_value::ConstValue; +use tailcall_valid::Validator; use super::blueprint; use super::directive::{to_const_directive, Directive}; use crate::core::blueprint::{Blueprint, Definition}; use crate::core::pos; -use crate::core::valid::Validator; fn to_directives(directives: &[Directive]) -> Vec> { directives diff --git a/src/core/blueprint/links.rs b/src/core/blueprint/links.rs index 47c83c63b4..bd9ad5a766 100644 --- a/src/core/blueprint/links.rs +++ b/src/core/blueprint/links.rs @@ -1,6 +1,7 @@ +use tailcall_valid::{Valid, ValidationError, Validator}; + use crate::core::config::{Link, LinkType}; use crate::core::directive::DirectiveCodec; -use crate::core::valid::{Valid, ValidationError, Validator}; pub struct Links; diff --git a/src/core/blueprint/mustache.rs b/src/core/blueprint/mustache.rs index a53e88f9e6..8845aaa5ac 100644 --- a/src/core/blueprint/mustache.rs +++ b/src/core/blueprint/mustache.rs @@ -1,8 +1,9 @@ +use tailcall_valid::{Valid, Validator}; + use super::FieldDefinition; use crate::core::config::{self, Config}; use crate::core::ir::model::{IO, IR}; use crate::core::scalar; -use crate::core::valid::{Valid, Validator}; struct MustachePartsValidator<'a> { type_of: &'a config::Type, @@ -179,10 +180,11 @@ impl FieldDefinition { #[cfg(test)] mod test { + use tailcall_valid::Validator; + use super::MustachePartsValidator; use crate::core::blueprint::{FieldDefinition, InputFieldDefinition}; use crate::core::config::{self, Config, Field}; - use crate::core::valid::Validator; use crate::core::Type; fn initialize_test_config_and_field() -> (Config, FieldDefinition) { diff --git a/src/core/blueprint/operators/apollo_federation.rs b/src/core/blueprint/operators/apollo_federation.rs index 992034d365..46c4a8e770 100644 --- a/src/core/blueprint/operators/apollo_federation.rs +++ b/src/core/blueprint/operators/apollo_federation.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::fmt::Write; use async_graphql::parser::types::ServiceDocument; +use tailcall_valid::{Valid, Validator}; use super::{compile_call, compile_expr, compile_graphql, compile_grpc, compile_http, compile_js}; use crate::core::blueprint::{Blueprint, Definition, TryFoldConfig}; @@ -9,7 +10,6 @@ use crate::core::config::{ ApolloFederation, ConfigModule, EntityResolver, Field, GraphQLOperationType, Resolver, }; use crate::core::ir::model::IR; -use crate::core::valid::{Valid, Validator}; use crate::core::Type; pub struct CompileEntityResolver<'a> { diff --git a/src/core/blueprint/operators/call.rs b/src/core/blueprint/operators/call.rs index ebf8a2b361..73afa763f7 100644 --- a/src/core/blueprint/operators/call.rs +++ b/src/core/blueprint/operators/call.rs @@ -1,11 +1,11 @@ use serde_json::Value; +use tailcall_valid::{Valid, ValidationError, Validator}; use crate::core::blueprint::*; use crate::core::config; use crate::core::config::{Field, GraphQLOperationType, Resolver}; use crate::core::ir::model::IR; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; pub fn update_call<'a>( operation_type: &'a GraphQLOperationType, diff --git a/src/core/blueprint/operators/enum_alias.rs b/src/core/blueprint/operators/enum_alias.rs index cc1406eed1..22eebd4965 100644 --- a/src/core/blueprint/operators/enum_alias.rs +++ b/src/core/blueprint/operators/enum_alias.rs @@ -1,11 +1,12 @@ use std::collections::HashMap; +use tailcall_valid::Valid; + use crate::core::blueprint::*; use crate::core::config; use crate::core::config::Field; use crate::core::ir::model::{Map, IR}; use crate::core::try_fold::TryFold; -use crate::core::valid::Valid; pub fn update_enum_alias<'a>( ) -> TryFold<'a, (&'a ConfigModule, &'a Field, &'a config::Type, &'a str), FieldDefinition, String> diff --git a/src/core/blueprint/operators/expr.rs b/src/core/blueprint/operators/expr.rs index 09dc6b7d7f..42d767487c 100644 --- a/src/core/blueprint/operators/expr.rs +++ b/src/core/blueprint/operators/expr.rs @@ -1,4 +1,5 @@ use async_graphql_value::ConstValue; +use tailcall_valid::{Valid, ValidationError, Validator}; use crate::core::blueprint::*; use crate::core::config; @@ -6,7 +7,6 @@ use crate::core::config::{Expr, Field, Resolver}; use crate::core::ir::model::IR; use crate::core::ir::model::IR::Dynamic; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; fn validate_data_with_schema( config: &config::Config, diff --git a/src/core/blueprint/operators/graphql.rs b/src/core/blueprint/operators/graphql.rs index d54547b714..ee25eb5fd1 100644 --- a/src/core/blueprint/operators/graphql.rs +++ b/src/core/blueprint/operators/graphql.rs @@ -1,5 +1,7 @@ use std::collections::{HashMap, HashSet}; +use tailcall_valid::{Valid, ValidationError, Validator}; + use crate::core::blueprint::FieldDefinition; use crate::core::config::{ Config, ConfigModule, Field, GraphQL, GraphQLOperationType, Resolver, Type, @@ -9,7 +11,6 @@ use crate::core::helpers; use crate::core::ir::model::{IO, IR}; use crate::core::ir::RelatedFields; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; fn create_related_fields( config: &Config, diff --git a/src/core/blueprint/operators/grpc.rs b/src/core/blueprint/operators/grpc.rs index 1cf22c28c8..3f730b109c 100644 --- a/src/core/blueprint/operators/grpc.rs +++ b/src/core/blueprint/operators/grpc.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use prost_reflect::prost_types::FileDescriptorSet; use prost_reflect::FieldDescriptor; +use tailcall_valid::{Valid, ValidationError, Validator}; use super::apply_select; use crate::core::blueprint::FieldDefinition; @@ -13,7 +14,6 @@ use crate::core::ir::model::{IO, IR}; use crate::core::json::JsonSchema; use crate::core::mustache::Mustache; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; use crate::core::{config, helpers}; fn to_url(grpc: &Grpc, method: &GrpcMethod) -> Valid { @@ -241,8 +241,9 @@ pub fn update_grpc<'a>( mod tests { use std::convert::TryFrom; + use tailcall_valid::ValidationError; + use super::GrpcMethod; - use crate::core::valid::ValidationError; #[test] fn try_from_grpc_method() { diff --git a/src/core/blueprint/operators/http.rs b/src/core/blueprint/operators/http.rs index c7e7bb4cce..6518388845 100644 --- a/src/core/blueprint/operators/http.rs +++ b/src/core/blueprint/operators/http.rs @@ -1,3 +1,5 @@ +use tailcall_valid::{Valid, ValidationError, Validator}; + use crate::core::blueprint::*; use crate::core::config::group_by::GroupBy; use crate::core::config::{Field, Resolver}; @@ -5,7 +7,6 @@ use crate::core::endpoint::Endpoint; use crate::core::http::{HttpFilter, Method, RequestTemplate}; use crate::core::ir::model::{IO, IR}; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; use crate::core::{config, helpers, Mustache}; pub fn compile_http( diff --git a/src/core/blueprint/operators/js.rs b/src/core/blueprint/operators/js.rs index cf61d20e19..2eb35ee423 100644 --- a/src/core/blueprint/operators/js.rs +++ b/src/core/blueprint/operators/js.rs @@ -1,9 +1,10 @@ +use tailcall_valid::{Valid, Validator}; + use crate::core::blueprint::FieldDefinition; use crate::core::config; use crate::core::config::{ConfigModule, Field, Resolver, JS}; use crate::core::ir::model::{IO, IR}; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, Validator}; pub struct CompileJs<'a> { pub js: &'a JS, diff --git a/src/core/blueprint/operators/modify.rs b/src/core/blueprint/operators/modify.rs index 32e7730b70..add132345a 100644 --- a/src/core/blueprint/operators/modify.rs +++ b/src/core/blueprint/operators/modify.rs @@ -1,9 +1,10 @@ +use tailcall_valid::Valid; + use crate::core::blueprint::*; use crate::core::config; use crate::core::config::Field; use crate::core::ir::model::IR; use crate::core::try_fold::TryFold; -use crate::core::valid::Valid; pub fn update_modify<'a>( ) -> TryFold<'a, (&'a ConfigModule, &'a Field, &'a config::Type, &'a str), FieldDefinition, String> diff --git a/src/core/blueprint/operators/protected.rs b/src/core/blueprint/operators/protected.rs index 87580dbcaa..9624650817 100644 --- a/src/core/blueprint/operators/protected.rs +++ b/src/core/blueprint/operators/protected.rs @@ -1,8 +1,9 @@ +use tailcall_valid::Valid; + use crate::core::blueprint::FieldDefinition; use crate::core::config::{self, ConfigModule, Field}; use crate::core::ir::model::IR; use crate::core::try_fold::TryFold; -use crate::core::valid::Valid; pub fn update_protected<'a>( type_name: &'a str, diff --git a/src/core/blueprint/operators/select.rs b/src/core/blueprint/operators/select.rs index 8af1c90401..f4e8eccc3a 100644 --- a/src/core/blueprint/operators/select.rs +++ b/src/core/blueprint/operators/select.rs @@ -1,8 +1,8 @@ use serde_json::Value; +use tailcall_valid::Valid; use crate::core::blueprint::DynamicValue; use crate::core::ir::model::IR; -use crate::core::valid::Valid; pub fn apply_select(input: (IR, &Option)) -> Valid { let (mut ir, select) = input; diff --git a/src/core/blueprint/schema.rs b/src/core/blueprint/schema.rs index d8a5211da2..8ecaf24651 100644 --- a/src/core/blueprint/schema.rs +++ b/src/core/blueprint/schema.rs @@ -1,11 +1,11 @@ use std::collections::{BTreeMap, HashSet}; use directive::to_directive; +use tailcall_valid::{Valid, Validator}; use crate::core::blueprint::*; use crate::core::config::{Config, Field, Type}; use crate::core::directive::DirectiveCodec; -use crate::core::valid::{Valid, Validator}; fn validate_query(config: &Config) -> Valid<(), String> { Valid::from_option( diff --git a/src/core/blueprint/server.rs b/src/core/blueprint/server.rs index 982fb3f61e..e8e0f54acd 100644 --- a/src/core/blueprint/server.rs +++ b/src/core/blueprint/server.rs @@ -6,11 +6,11 @@ use std::time::Duration; use derive_setters::Setters; use http::header::{HeaderMap, HeaderName, HeaderValue}; use rustls_pki_types::CertificateDer; +use tailcall_valid::{Valid, ValidationError, Validator}; use super::Auth; use crate::core::blueprint::Cors; use crate::core::config::{self, ConfigModule, HttpVersion, PrivateKey, Routes}; -use crate::core::valid::{Valid, ValidationError, Validator}; #[derive(Clone, Debug, Setters)] pub struct Server { diff --git a/src/core/blueprint/telemetry.rs b/src/core/blueprint/telemetry.rs index 6182b86fc1..f7b131c2ec 100644 --- a/src/core/blueprint/telemetry.rs +++ b/src/core/blueprint/telemetry.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use http::header::{HeaderMap, HeaderName, HeaderValue}; +use tailcall_valid::{Valid, ValidationError, Validator}; use url::Url; use super::TryFoldConfig; @@ -9,7 +10,6 @@ use crate::core::config::{ }; use crate::core::directive::DirectiveCodec; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, ValidationError, Validator}; #[derive(Debug, Clone)] pub struct OtlpExporter { @@ -99,8 +99,9 @@ fn validate_graph_ref(graph_ref: &str) -> Valid<(), String> { #[cfg(test)] mod tests { + use tailcall_valid::Valid; + use super::validate_graph_ref; - use crate::core::valid::Valid; #[test] fn test_validate_graph_ref() { diff --git a/src/core/blueprint/union_resolver.rs b/src/core/blueprint/union_resolver.rs index ceb47d5d4f..73604742cb 100644 --- a/src/core/blueprint/union_resolver.rs +++ b/src/core/blueprint/union_resolver.rs @@ -1,9 +1,10 @@ +use tailcall_valid::{Valid, Validator}; + use crate::core::blueprint::FieldDefinition; use crate::core::config::{ConfigModule, Discriminate, Field, Type, Union}; use crate::core::ir::model::IR; use crate::core::ir::Discriminator; use crate::core::try_fold::TryFold; -use crate::core::valid::{Valid, Validator}; fn compile_union_resolver( union_name: &str, diff --git a/src/core/blueprint/upstream.rs b/src/core/blueprint/upstream.rs index 15171f90d5..e8304ac224 100644 --- a/src/core/blueprint/upstream.rs +++ b/src/core/blueprint/upstream.rs @@ -1,9 +1,9 @@ use std::collections::BTreeSet; use derive_setters::Setters; +use tailcall_valid::{Valid, ValidationError, Validator}; use crate::core::config::{self, Batch, ConfigModule}; -use crate::core::valid::{Valid, ValidationError, Validator}; #[derive(PartialEq, Eq, Clone, Debug, schemars::JsonSchema)] pub struct Proxy { diff --git a/src/core/config/config.rs b/src/core/config/config.rs index 4f3250f794..070ec7499b 100644 --- a/src/core/config/config.rs +++ b/src/core/config/config.rs @@ -11,6 +11,7 @@ use strum::IntoEnumIterator; use tailcall_typedefs_common::directive_definition::DirectiveDefinition; use tailcall_typedefs_common::input_definition::InputDefinition; use tailcall_typedefs_common::ServiceDocumentBuilder; +use tailcall_valid::{Valid, Validator}; use super::directive::Directive; use super::from_document::from_document; @@ -24,7 +25,6 @@ use crate::core::is_default; use crate::core::macros::MergeRight; use crate::core::merge_right::MergeRight; use crate::core::scalar::Scalar; -use crate::core::valid::{Valid, Validator}; #[derive( Serialize, diff --git a/src/core/config/config_module.rs b/src/core/config/config_module.rs index 89bcbbd2f5..b7c617ca84 100644 --- a/src/core/config/config_module.rs +++ b/src/core/config/config_module.rs @@ -4,13 +4,13 @@ use std::ops::Deref; use jsonwebtoken::jwk::JwkSet; use prost_reflect::prost_types::{FileDescriptorProto, FileDescriptorSet}; use rustls_pki_types::{CertificateDer, PrivateKeyDer}; +use tailcall_valid::{Valid, Validator}; use crate::core::config::Config; use crate::core::macros::MergeRight; use crate::core::merge_right::MergeRight; use crate::core::proto_reader::ProtoMetadata; use crate::core::rest::{EndpointSet, Unchecked}; -use crate::core::valid::{Valid, Validator}; use crate::core::Transform; mod merge; diff --git a/src/core/config/config_module/merge.rs b/src/core/config/config_module/merge.rs index 57c43fee19..0c145234d2 100644 --- a/src/core/config/config_module/merge.rs +++ b/src/core/config/config_module/merge.rs @@ -1,12 +1,12 @@ use std::collections::BTreeMap; use indexmap::IndexMap; +use tailcall_valid::{Valid, Validator}; use super::{Cache, ConfigModule}; use crate::core; use crate::core::config::{Arg, Config, Enum, Field, Type}; use crate::core::merge_right::MergeRight; -use crate::core::valid::{Valid, Validator}; use crate::core::variance::{Contravariant, Covariant, Invariant}; impl core::Type { @@ -396,10 +396,10 @@ where mod tests { use anyhow::Result; use insta::assert_snapshot; + use tailcall_valid::Validator; use super::*; use crate::core::config::ConfigModule; - use crate::core::valid::Validator; use crate::include_config; #[test] diff --git a/src/core/config/directive.rs b/src/core/config/directive.rs index ba8d286616..36e0500703 100644 --- a/src/core/config/directive.rs +++ b/src/core/config/directive.rs @@ -5,8 +5,8 @@ use async_graphql::Name; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value; +use tailcall_valid::{Valid, ValidationError, Validator}; -use crate::core::valid::{Valid, ValidationError, Validator}; use crate::core::{is_default, pos}; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema)] @@ -49,9 +49,9 @@ mod tests { use async_graphql::parser::types::ConstDirective; use async_graphql_value::Name; use pretty_assertions::assert_eq; + use tailcall_valid::Validator; use super::*; - use crate::core::valid::Validator; #[test] fn test_to_const_directive() { diff --git a/src/core/config/directives/telemetry.rs b/src/core/config/directives/telemetry.rs index 14632fcecf..108ff2aab3 100644 --- a/src/core/config/directives/telemetry.rs +++ b/src/core/config/directives/telemetry.rs @@ -1,6 +1,7 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use tailcall_macros::{DirectiveDefinition, InputDefinition}; +use tailcall_valid::Validator; use crate::core::config::{Apollo, ConfigReaderContext, KeyValue}; use crate::core::helpers::headers::to_mustache_headers; @@ -8,7 +9,6 @@ use crate::core::is_default; use crate::core::macros::MergeRight; use crate::core::merge_right::MergeRight; use crate::core::mustache::Mustache; -use crate::core::valid::Validator; mod defaults { pub mod prometheus { diff --git a/src/core/config/from_document.rs b/src/core/config/from_document.rs index 1764105ac0..3ccd7b72b6 100644 --- a/src/core/config/from_document.rs +++ b/src/core/config/from_document.rs @@ -9,6 +9,7 @@ use async_graphql::parser::Positioned; use async_graphql::Name; use async_graphql_value::ConstValue; use indexmap::IndexMap; +use tailcall_valid::{Valid, ValidationError, Validator}; use super::directive::{to_directive, Directive}; use super::{Alias, Discriminate, Resolver, Telemetry, FEDERATION_DIRECTIVES}; @@ -17,7 +18,6 @@ use crate::core::config::{ Variant, }; use crate::core::directive::DirectiveCodec; -use crate::core::valid::{Valid, ValidationError, Validator}; const DEFAULT_SCHEMA_DEFINITION: &SchemaDefinition = &SchemaDefinition { extend: false, diff --git a/src/core/config/into_document.rs b/src/core/config/into_document.rs index 1d020edfe7..b06ff84311 100644 --- a/src/core/config/into_document.rs +++ b/src/core/config/into_document.rs @@ -1,12 +1,12 @@ use async_graphql::parser::types::*; use async_graphql::Positioned; use async_graphql_value::{ConstValue, Name}; +use tailcall_valid::Validator; use super::directive::to_const_directive; use super::Config; use crate::core::directive::DirectiveCodec; use crate::core::pos; -use crate::core::valid::Validator; fn transform_default_value(value: Option) -> Option { value.map(ConstValue::from_json).and_then(Result::ok) diff --git a/src/core/config/reader.rs b/src/core/config/reader.rs index 5eb4b31494..fc6c6c9ebc 100644 --- a/src/core/config/reader.rs +++ b/src/core/config/reader.rs @@ -4,6 +4,7 @@ use rustls_pemfile; use rustls_pki_types::{ CertificateDer, PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer, PrivateSec1KeyDer, }; +use tailcall_valid::{Valid, Validator}; use url::Url; use super::{ConfigModule, Content, Link, LinkType, PrivateKey}; @@ -12,7 +13,6 @@ use crate::core::proto_reader::ProtoReader; use crate::core::resource_reader::{Cached, Resource, ResourceReader}; use crate::core::rest::EndpointSet; use crate::core::runtime::TargetRuntime; -use crate::core::valid::{Valid, Validator}; use crate::core::variance::Invariant; /// Reads the configuration from a file or from an HTTP URL and resolves all diff --git a/src/core/config/resolver.rs b/src/core/config/resolver.rs index e1d7531738..e30d3150ed 100644 --- a/src/core/config/resolver.rs +++ b/src/core/config/resolver.rs @@ -2,10 +2,10 @@ use async_graphql::parser::types::ConstDirective; use async_graphql::Positioned; use serde::{Deserialize, Serialize}; use tailcall_macros::{CustomResolver, MergeRight}; +use tailcall_valid::{Valid, Validator}; use super::{Call, EntityResolver, Expr, GraphQL, Grpc, Http, JS}; use crate::core::directive::DirectiveCodec; -use crate::core::valid::{Valid, Validator}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum ApolloFederation { diff --git a/src/core/config/source.rs b/src/core/config/source.rs index 34c92f5c2f..24e6adc110 100644 --- a/src/core/config/source.rs +++ b/src/core/config/source.rs @@ -1,9 +1,9 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use tailcall_valid::{ValidationError, Validator}; use thiserror::Error; use super::Config; -use crate::core::valid::{ValidationError, Validator}; #[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "camelCase")] diff --git a/src/core/config/transformer/ambiguous_type.rs b/src/core/config/transformer/ambiguous_type.rs index 1748de4974..994de6557b 100644 --- a/src/core/config/transformer/ambiguous_type.rs +++ b/src/core/config/transformer/ambiguous_type.rs @@ -1,8 +1,9 @@ use std::collections::HashMap; +use tailcall_valid::{Valid, Validator}; + use crate::core::config::Config; use crate::core::transform::Transform; -use crate::core::valid::{Valid, Validator}; /// Resolves the ambiguous types by renaming the input and /// output types. The resolver function is called whenever is a conflict is @@ -153,13 +154,13 @@ mod tests { use insta::assert_snapshot; use prost_reflect::prost_types::FileDescriptorSet; use tailcall_fixtures::protobuf; + use tailcall_valid::Validator; use crate::core::config::transformer::AmbiguousType; use crate::core::config::{self, Config}; use crate::core::generator::{Generator, Input}; use crate::core::proto_reader::ProtoMetadata; use crate::core::transform::Transform; - use crate::core::valid::Validator; use crate::core::Type; fn build_qry(mut config: Config) -> Config { diff --git a/src/core/config/transformer/consolidate_url/consolidate_url.rs b/src/core/config/transformer/consolidate_url/consolidate_url.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/core/config/transformer/flatten_single_field.rs b/src/core/config/transformer/flatten_single_field.rs index d6d57ce457..b153ce87f9 100644 --- a/src/core/config/transformer/flatten_single_field.rs +++ b/src/core/config/transformer/flatten_single_field.rs @@ -1,8 +1,9 @@ use std::collections::HashSet; +use tailcall_valid::Valid; + use crate::core::config::{AddField, Config, Omit}; use crate::core::transform::Transform; -use crate::core::valid::Valid; /// Flat single field type and inline to Query directly by addField #[derive(Default)] @@ -83,11 +84,11 @@ mod test { use std::fs; use tailcall_fixtures::configs; + use tailcall_valid::Validator; use super::FlattenSingleField; use crate::core::config::Config; use crate::core::transform::Transform; - use crate::core::valid::Validator; fn read_fixture(path: &str) -> String { fs::read_to_string(path).unwrap() diff --git a/src/core/config/transformer/improve_type_names.rs b/src/core/config/transformer/improve_type_names.rs index 1658b95010..a2cdfaa69b 100644 --- a/src/core/config/transformer/improve_type_names.rs +++ b/src/core/config/transformer/improve_type_names.rs @@ -1,12 +1,12 @@ use std::collections::{BTreeMap, HashSet}; use convert_case::{Case, Casing}; +use tailcall_valid::Valid; use super::RenameTypes; use crate::core::config::Config; use crate::core::generator::PREFIX; use crate::core::transform::Transform; -use crate::core::valid::Valid; #[derive(Debug, Default)] struct CandidateStats { @@ -132,11 +132,11 @@ mod test { use anyhow::Ok; use tailcall_fixtures::configs; + use tailcall_valid::Validator; use super::ImproveTypeNames; use crate::core::config::Config; use crate::core::transform::Transform; - use crate::core::valid::Validator; fn read_fixture(path: &str) -> String { fs::read_to_string(path).unwrap() diff --git a/src/core/config/transformer/merge_types/similarity.rs b/src/core/config/transformer/merge_types/similarity.rs index 45b87c9b53..f0ca65d3fa 100644 --- a/src/core/config/transformer/merge_types/similarity.rs +++ b/src/core/config/transformer/merge_types/similarity.rs @@ -1,8 +1,9 @@ +use tailcall_valid::{Valid, Validator}; + use super::pair_map::PairMap; use super::pair_set::PairSet; use crate::core::config::{Config, Type}; use crate::core::scalar::Scalar; -use crate::core::valid::{Valid, Validator}; /// Given Two types,it tells similarity between two types based on a specified /// threshold. @@ -137,9 +138,10 @@ impl<'a> Similarity<'a> { #[cfg(test)] mod test { + use tailcall_valid::Validator; + use super::Similarity; use crate::core::config::{config, Config, Field}; - use crate::core::valid::Validator; use crate::core::Type; #[test] diff --git a/src/core/config/transformer/merge_types/type_merger.rs b/src/core/config/transformer/merge_types/type_merger.rs index c5d83950ac..4cf82f8e45 100644 --- a/src/core/config/transformer/merge_types/type_merger.rs +++ b/src/core/config/transformer/merge_types/type_merger.rs @@ -1,6 +1,7 @@ use std::collections::HashSet; use indexmap::{IndexMap, IndexSet}; +use tailcall_valid::{Valid, Validator}; use super::mergeable_types::MergeableTypes; use super::similarity::Similarity; @@ -9,7 +10,6 @@ use crate::core::generator::PREFIX; use crate::core::merge_right::MergeRight; use crate::core::scalar::Scalar; use crate::core::transform::Transform; -use crate::core::valid::{Valid, Validator}; pub struct TypeMerger { /// threshold required for the merging process. @@ -245,11 +245,11 @@ impl Transform for TypeMerger { #[cfg(test)] mod test { use tailcall_fixtures; + use tailcall_valid::Validator; use super::TypeMerger; use crate::core::config::{Config, Field, Type}; use crate::core::transform::Transform; - use crate::core::valid::Validator; #[test] fn test_cyclic_merge_case() -> anyhow::Result<()> { diff --git a/src/core/config/transformer/nested_unions.rs b/src/core/config/transformer/nested_unions.rs index 29e09162bf..faab9d98ed 100644 --- a/src/core/config/transformer/nested_unions.rs +++ b/src/core/config/transformer/nested_unions.rs @@ -1,8 +1,9 @@ use std::collections::{BTreeMap, BTreeSet, HashSet}; +use tailcall_valid::{Valid, Validator}; + use crate::core::config::{Config, Union}; use crate::core::transform::Transform; -use crate::core::valid::{Valid, Validator}; /// Transforms unions by replacing each nested union in union definition /// recursively by their actual types @@ -71,11 +72,11 @@ impl<'cfg> Visitor<'cfg> { #[cfg(test)] mod tests { use insta::assert_snapshot; + use tailcall_valid::Validator; use super::NestedUnions; use crate::core::config::Config; use crate::core::transform::Transform; - use crate::core::valid::Validator; #[test] fn test_nested_unions() { diff --git a/src/core/config/transformer/preset.rs b/src/core/config/transformer/preset.rs index ac54401473..be70315674 100644 --- a/src/core/config/transformer/preset.rs +++ b/src/core/config/transformer/preset.rs @@ -28,10 +28,7 @@ impl Transform for Preset { type Value = Config; type Error = String; - fn transform( - &self, - config: Self::Value, - ) -> crate::core::valid::Valid { + fn transform(&self, config: Self::Value) -> tailcall_valid::Valid { transform::default() .pipe(super::Required) .pipe(super::TreeShake.when(self.tree_shake)) diff --git a/src/core/config/transformer/rename_types.rs b/src/core/config/transformer/rename_types.rs index 685d77646b..26d9b599c9 100644 --- a/src/core/config/transformer/rename_types.rs +++ b/src/core/config/transformer/rename_types.rs @@ -1,9 +1,9 @@ use std::collections::HashSet; use indexmap::IndexMap; +use tailcall_valid::{Valid, Validator}; use crate::core::config::Config; -use crate::core::valid::{Valid, Validator}; use crate::core::Transform; /// A transformer that renames existing types by replacing them with suggested @@ -142,11 +142,11 @@ impl Transform for RenameTypes { mod test { use indexmap::IndexMap; use maplit::hashmap; + use tailcall_valid::{ValidationError, Validator}; use super::RenameTypes; use crate::core::config::Config; use crate::core::transform::Transform; - use crate::core::valid::{ValidationError, Validator}; #[test] fn test_rename_type() { diff --git a/src/core/config/transformer/required.rs b/src/core/config/transformer/required.rs index e8ba0c2803..53307720c3 100644 --- a/src/core/config/transformer/required.rs +++ b/src/core/config/transformer/required.rs @@ -10,10 +10,7 @@ impl Transform for Required { type Value = Config; type Error = String; - fn transform( - &self, - config: Self::Value, - ) -> crate::core::valid::Valid { + fn transform(&self, config: Self::Value) -> tailcall_valid::Valid { transform::default() .pipe(super::Subgraph) .pipe(super::NestedUnions) diff --git a/src/core/config/transformer/subgraph.rs b/src/core/config/transformer/subgraph.rs index 014d8ba542..ed1bf950d8 100644 --- a/src/core/config/transformer/subgraph.rs +++ b/src/core/config/transformer/subgraph.rs @@ -5,6 +5,7 @@ use std::fmt::{Display, Write}; use std::ops::Deref; use tailcall_macros::MergeRight; +use tailcall_valid::{Valid, Validator}; use crate::core::config::directive::to_directive; use crate::core::config::{ @@ -14,7 +15,6 @@ use crate::core::config::{ use crate::core::directive::DirectiveCodec; use crate::core::merge_right::MergeRight; use crate::core::mustache::Segment; -use crate::core::valid::{Valid, Validator}; use crate::core::{Mustache, Transform, Type}; const ENTITIES_FIELD_NAME: &str = "_entities"; diff --git a/src/core/config/transformer/tree_shake.rs b/src/core/config/transformer/tree_shake.rs index a80ead6c06..1edc6d27d2 100644 --- a/src/core/config/transformer/tree_shake.rs +++ b/src/core/config/transformer/tree_shake.rs @@ -1,6 +1,7 @@ +use tailcall_valid::Valid; + use crate::core::config::Config; use crate::core::transform::Transform; -use crate::core::valid::Valid; /// `RemoveUnused` is responsible for removing unused types from a /// configuration. diff --git a/src/core/config/transformer/union_input_type.rs b/src/core/config/transformer/union_input_type.rs index b43132dc68..906650dd6d 100644 --- a/src/core/config/transformer/union_input_type.rs +++ b/src/core/config/transformer/union_input_type.rs @@ -1,9 +1,10 @@ use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use tailcall_valid::Valid; + use crate::core::config::{Arg, Config, Field, Type}; use crate::core::transform::Transform; -use crate::core::valid::Valid; /// Transforms unions inside the input types by replacing actual unions /// with multiple variants of the parent type, with each field resolved @@ -281,11 +282,11 @@ impl<'cfg> Visitor<'cfg> { #[cfg(test)] mod tests { use insta::assert_snapshot; + use tailcall_valid::Validator; use super::UnionInputType; use crate::core::config::Config; use crate::core::transform::Transform; - use crate::core::valid::Validator; #[test] fn test_union() { diff --git a/src/core/directive.rs b/src/core/directive.rs index 0130310ec6..d4cf6cb197 100644 --- a/src/core/directive.rs +++ b/src/core/directive.rs @@ -3,9 +3,9 @@ use async_graphql::{Name, Positioned}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use serde_path_to_error::deserialize; +use tailcall_valid::{Valid, ValidationError, Validator}; use super::pos; -use crate::core::valid::{Valid, ValidationError, Validator}; pub trait DirectiveCodec: Sized { fn directive_name() -> String; diff --git a/src/core/errata.rs b/src/core/errata.rs index 6f681511a2..6864abf725 100644 --- a/src/core/errata.rs +++ b/src/core/errata.rs @@ -2,9 +2,9 @@ use std::fmt::{Debug, Display}; use colored::Colorize; use derive_setters::Setters; +use tailcall_valid::ValidationError; use crate::core::error::Error as CoreError; -use crate::core::valid::ValidationError; /// The moral equivalent of a serde_json::Value but for errors. /// It's a data structure like Value that can hold any error in an untyped @@ -235,9 +235,9 @@ impl From> for Errata { mod tests { use pretty_assertions::assert_eq; use stripmargin::StripMargin; + use tailcall_valid::Cause; use super::*; - use crate::core::valid::Cause; #[test] fn test_no_newline() { diff --git a/src/core/generator/from_json.rs b/src/core/generator/from_json.rs index 1f380d8ced..c33d875f2d 100644 --- a/src/core/generator/from_json.rs +++ b/src/core/generator/from_json.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use convert_case::{Case, Casing}; use serde_json::Value; +use tailcall_valid::{Valid, Validator}; use url::Url; use super::json::{self, GraphQLTypesGenerator}; @@ -11,7 +12,6 @@ use crate::core::config::{Config, GraphQLOperationType}; use crate::core::http::Method; use crate::core::merge_right::MergeRight; use crate::core::transform::{Transform, TransformerOps}; -use crate::core::valid::{Valid, Validator}; pub struct RequestSample { pub url: Url, @@ -138,11 +138,12 @@ impl Transform for FromJsonGenerator<'_> { #[cfg(test)] mod tests { + use tailcall_valid::Validator; + use crate::core::config::transformer::Preset; use crate::core::generator::generator::test::JsonFixture; use crate::core::generator::{FromJsonGenerator, NameGenerator, RequestSample}; use crate::core::transform::TransformerOps; - use crate::core::valid::Validator; #[tokio::test] async fn generate_config_from_json() -> anyhow::Result<()> { diff --git a/src/core/generator/from_proto.rs b/src/core/generator/from_proto.rs index 3066e704c5..b85aca8efa 100644 --- a/src/core/generator/from_proto.rs +++ b/src/core/generator/from_proto.rs @@ -7,6 +7,7 @@ use prost_reflect::prost_types::{ DescriptorProto, EnumDescriptorProto, FileDescriptorSet, ServiceDescriptorProto, SourceCodeInfo, }; use serde_json::Value; +use tailcall_valid::Validator; use super::graphql_type::{GraphQLType, Unparsed}; use super::proto::comments_builder::CommentsBuilder; @@ -15,7 +16,6 @@ use super::proto::path_field::PathField; use crate::core::config::transformer::{AmbiguousType, TreeShake}; use crate::core::config::{self, Arg, Config, Enum, Field, Grpc, Resolver, Union, Variant}; use crate::core::transform::{Transform, TransformerOps}; -use crate::core::valid::Validator; use crate::core::Type; /// Assists in the mapping and retrieval of proto type names to custom formatted diff --git a/src/core/generator/generator.rs b/src/core/generator/generator.rs index 92c9c450e6..4a06071bbb 100644 --- a/src/core/generator/generator.rs +++ b/src/core/generator/generator.rs @@ -4,6 +4,7 @@ use derive_setters::Setters; use prost_reflect::prost_types::FileDescriptorSet; use prost_reflect::DescriptorPool; use serde_json::Value; +use tailcall_valid::Validator; use url::Url; use super::from_proto::from_proto; @@ -13,7 +14,6 @@ use crate::core::http::Method; use crate::core::merge_right::MergeRight; use crate::core::proto_reader::ProtoMetadata; use crate::core::transform::{Transform, TransformerOps}; -use crate::core::valid::Validator; /// Generator offers an abstraction over the actual config generators and allows /// to generate the single config from multiple sources. i.e (Protobuf and Json) diff --git a/src/core/generator/json/operation_generator.rs b/src/core/generator/json/operation_generator.rs index a904ae8679..f30b489a6d 100644 --- a/src/core/generator/json/operation_generator.rs +++ b/src/core/generator/json/operation_generator.rs @@ -1,10 +1,10 @@ use convert_case::{Case, Casing}; +use tailcall_valid::Valid; use super::http_directive_generator::HttpDirectiveGenerator; use crate::core::config::{Arg, Config, Field, GraphQLOperationType, Resolver}; use crate::core::generator::json::types_generator::TypeGenerator; use crate::core::generator::{NameGenerator, RequestSample, PREFIX}; -use crate::core::valid::Valid; use crate::core::{config, Type}; pub struct OperationTypeGenerator; @@ -76,11 +76,12 @@ impl OperationTypeGenerator { mod test { use std::collections::BTreeMap; + use tailcall_valid::Validator; + use super::OperationTypeGenerator; use crate::core::config::{Config, Field, Type}; use crate::core::generator::{NameGenerator, RequestSample}; use crate::core::http::Method; - use crate::core::valid::Validator; #[test] fn test_query() { diff --git a/src/core/generator/json/schema_generator.rs b/src/core/generator/json/schema_generator.rs index a2d5a778a3..a466924b92 100644 --- a/src/core/generator/json/schema_generator.rs +++ b/src/core/generator/json/schema_generator.rs @@ -1,10 +1,10 @@ use std::collections::BTreeSet; use convert_case::{Case, Casing}; +use tailcall_valid::Valid; use crate::core::config::{Config, GraphQLOperationType}; use crate::core::transform::Transform; -use crate::core::valid::Valid; pub struct SchemaGenerator<'a> { operation_type: &'a GraphQLOperationType, @@ -52,10 +52,11 @@ impl Transform for SchemaGenerator<'_> { mod test { use std::collections::BTreeSet; + use tailcall_valid::Validator; + use super::SchemaGenerator; use crate::core::config::GraphQLOperationType; use crate::core::transform::Transform; - use crate::core::valid::Validator; #[test] fn test_schema_generator_with_mutation() { diff --git a/src/core/generator/json/types_generator.rs b/src/core/generator/json/types_generator.rs index 9e77fb7042..923afb1393 100644 --- a/src/core/generator/json/types_generator.rs +++ b/src/core/generator/json/types_generator.rs @@ -1,4 +1,5 @@ use serde_json::{Map, Value}; +use tailcall_valid::Valid; use super::OperationTypeGenerator; use crate::core::config::{Config, Field, Type}; @@ -6,7 +7,6 @@ use crate::core::generator::{NameGenerator, RequestSample}; use crate::core::helpers::gql_type::{is_primitive, is_valid_field_name, to_gql_type}; use crate::core::scalar::Scalar; use crate::core::transform::Transform; -use crate::core::valid::Valid; struct JSONValidator; diff --git a/src/core/helpers/body.rs b/src/core/helpers/body.rs index 0f2b582577..5e44643d85 100644 --- a/src/core/helpers/body.rs +++ b/src/core/helpers/body.rs @@ -1,8 +1,8 @@ use serde_json::Value; +use tailcall_valid::Valid; use crate::core::grpc::request_template::RequestBody; use crate::core::mustache::Mustache; -use crate::core::valid::Valid; pub fn to_body(body: Option<&Value>) -> Valid, String> { let Some(body) = body else { @@ -21,10 +21,11 @@ pub fn to_body(body: Option<&Value>) -> Valid, String> { #[cfg(test)] mod tests { + use tailcall_valid::Valid; + use super::to_body; use crate::core::grpc::request_template::RequestBody; use crate::core::mustache::Mustache; - use crate::core::valid::Valid; #[test] fn no_body() { diff --git a/src/core/helpers/headers.rs b/src/core/helpers/headers.rs index 38280ed1bd..76da574439 100644 --- a/src/core/helpers/headers.rs +++ b/src/core/helpers/headers.rs @@ -1,8 +1,8 @@ use http::header::HeaderName; +use tailcall_valid::{Valid, ValidationError, Validator}; use crate::core::config::KeyValue; use crate::core::mustache::Mustache; -use crate::core::valid::{Valid, ValidationError, Validator}; pub type MustacheHeaders = Vec<(HeaderName, Mustache)>; @@ -25,11 +25,11 @@ pub fn to_mustache_headers(headers: &[KeyValue]) -> Valid Result<()> { diff --git a/src/core/helpers/url.rs b/src/core/helpers/url.rs index 0f716185ca..51b65b36cf 100644 --- a/src/core/helpers/url.rs +++ b/src/core/helpers/url.rs @@ -1,5 +1,6 @@ +use tailcall_valid::Valid; + use crate::core::mustache::Mustache; -use crate::core::valid::Valid; pub fn to_url(url: &str) -> Valid { Valid::succeed(Mustache::parse(url)) @@ -11,8 +12,9 @@ mod tests { #[test] fn parse_url() { + use tailcall_valid::Valid; + use crate::core::mustache::Mustache; - use crate::core::valid::Valid; let url = to_url("http://localhost:3000"); diff --git a/src/core/http/request_handler.rs b/src/core/http/request_handler.rs index bfb1c5972b..712929ee0d 100644 --- a/src/core/http/request_handler.rs +++ b/src/core/http/request_handler.rs @@ -377,13 +377,14 @@ pub async fn handle_request( #[cfg(test)] mod test { + use tailcall_valid::Validator; + use super::*; use crate::core::async_graphql_hyper::GraphQLRequest; use crate::core::blueprint::Blueprint; use crate::core::config::{Config, ConfigModule, Routes}; use crate::core::rest::EndpointSet; use crate::core::runtime::test::init; - use crate::core::valid::Validator; #[tokio::test] async fn test_health_endpoint() -> anyhow::Result<()> { diff --git a/src/core/ir/discriminator.rs b/src/core/ir/discriminator.rs index 983168a131..f1d8834bda 100644 --- a/src/core/ir/discriminator.rs +++ b/src/core/ir/discriminator.rs @@ -6,10 +6,10 @@ use std::collections::BTreeSet; use anyhow::{bail, Result}; use async_graphql::Value; use keyed_discriminator::KeyedDiscriminator; +use tailcall_valid::{Valid, Validator}; use type_field_discriminator::TypeFieldDiscriminator; use crate::core::json::{JsonLike, JsonObjectLike}; -use crate::core::valid::{Valid, Validator}; /// Resolver for `__typename` of Union and Interface types. /// diff --git a/src/core/ir/discriminator/keyed_discriminator.rs b/src/core/ir/discriminator/keyed_discriminator.rs index a8ae0d1f02..b39b73238c 100644 --- a/src/core/ir/discriminator/keyed_discriminator.rs +++ b/src/core/ir/discriminator/keyed_discriminator.rs @@ -2,9 +2,9 @@ use std::collections::BTreeSet; use anyhow::{bail, Result}; use async_graphql::Value; +use tailcall_valid::Valid; use super::TypedValue; -use crate::core::valid::Valid; /// Resolver for `__typename` of Union and Interface types. /// @@ -82,10 +82,10 @@ impl KeyedDiscriminator { mod tests { use async_graphql::Value; use serde_json::json; + use tailcall_valid::Validator; use test_log::test; use super::KeyedDiscriminator; - use crate::core::valid::Validator; #[test] fn test_keyed_discriminator_positive() { diff --git a/src/core/ir/discriminator/type_field_discriminator.rs b/src/core/ir/discriminator/type_field_discriminator.rs index a79c1856c4..ae5a8af5c5 100644 --- a/src/core/ir/discriminator/type_field_discriminator.rs +++ b/src/core/ir/discriminator/type_field_discriminator.rs @@ -2,10 +2,10 @@ use std::collections::BTreeSet; use anyhow::{bail, Result}; use async_graphql::Value; +use tailcall_valid::Valid; use super::TypedValue; use crate::core::json::JsonLike; -use crate::core::valid::Valid; /// Resolver for `__typename` of Union and Interface types. /// @@ -80,10 +80,10 @@ impl TypeFieldDiscriminator { mod tests { use async_graphql::Value; use serde_json::json; + use tailcall_valid::Validator; use test_log::test; use super::TypeFieldDiscriminator; - use crate::core::valid::Validator; #[test] fn test_type_field_positive() { diff --git a/src/core/ir/error.rs b/src/core/ir/error.rs index 9246caba49..ac646429de 100644 --- a/src/core/ir/error.rs +++ b/src/core/ir/error.rs @@ -91,8 +91,8 @@ impl ErrorExtensions for Error { } } -impl<'a> From> for Error { - fn from(value: crate::core::valid::ValidationError<&'a str>) -> Self { +impl<'a> From> for Error { + fn from(value: tailcall_valid::ValidationError<&'a str>) -> Self { Error::APIValidation( value .as_vec() diff --git a/src/core/ir/eval_http.rs b/src/core/ir/eval_http.rs index 446eb9009a..c69b73c0ed 100644 --- a/src/core/ir/eval_http.rs +++ b/src/core/ir/eval_http.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use async_graphql::from_value; use reqwest::Request; +use tailcall_valid::Validator; use super::model::DataLoaderId; use super::{EvalContext, ResolverContextLike}; @@ -14,7 +15,6 @@ use crate::core::http::{ }; use crate::core::ir::Error; use crate::core::json::JsonLike; -use crate::core::valid::Validator; use crate::core::{grpc, http, worker, WorkerIO}; /// diff --git a/src/core/jit/builder.rs b/src/core/jit/builder.rs index f9d73756cd..26ab6d1f66 100644 --- a/src/core/jit/builder.rs +++ b/src/core/jit/builder.rs @@ -359,12 +359,12 @@ impl Builder { #[cfg(test)] mod tests { use pretty_assertions::assert_eq; + use tailcall_valid::Validator; use super::*; use crate::core::blueprint::Blueprint; use crate::core::config::Config; use crate::core::jit::builder::Builder; - use crate::core::valid::Validator; const CONFIG: &str = include_str!("./fixtures/jsonplaceholder-mutation.graphql"); diff --git a/src/core/jit/context.rs b/src/core/jit/context.rs index 1d00fd32a6..fb156a04b0 100644 --- a/src/core/jit/context.rs +++ b/src/core/jit/context.rs @@ -111,6 +111,7 @@ impl ResolverContextLike for Context<'_, ConstValue, ConstValue> { #[cfg(test)] mod test { use async_graphql_value::ConstValue; + use tailcall_valid::Validator; use super::{Context, RequestContext}; use crate::core::blueprint::Blueprint; @@ -118,7 +119,6 @@ mod test { use crate::core::ir::ResolverContextLike; use crate::core::jit::transform::InputResolver; use crate::core::jit::{OperationPlan, Request}; - use crate::core::valid::Validator; fn setup(query: &str) -> anyhow::Result> { let sdl = std::fs::read_to_string(tailcall_fixtures::configs::JSONPLACEHOLDER)?; diff --git a/src/core/jit/exec_const.rs b/src/core/jit/exec_const.rs index ddaeddd4ac..7f26bce003 100644 --- a/src/core/jit/exec_const.rs +++ b/src/core/jit/exec_const.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use async_graphql_value::{ConstValue, Value}; use futures_util::future::join_all; +use tailcall_valid::Validator; use super::context::Context; use super::exec::{Executor, IRExecutor}; @@ -15,7 +16,6 @@ use crate::core::ir::{self, EvalContext}; use crate::core::jit::synth::Synth; use crate::core::jit::transform::InputResolver; use crate::core::json::{JsonLike, JsonLikeList}; -use crate::core::valid::Validator; use crate::core::Transform; /// A specialized executor that executes with async_graphql::Value diff --git a/src/core/jit/fixtures/jp.rs b/src/core/jit/fixtures/jp.rs index 9f457baf27..2d0c99b45c 100644 --- a/src/core/jit/fixtures/jp.rs +++ b/src/core/jit/fixtures/jp.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use serde::Deserialize; +use tailcall_valid::Validator; use crate::core::blueprint::Blueprint; use crate::core::config::{Config, ConfigModule}; @@ -10,7 +11,6 @@ use crate::core::jit::synth::Synth; use crate::core::jit::transform::InputResolver; use crate::core::jit::{transform, Field, OperationPlan, Variables}; use crate::core::json::{JsonLike, JsonObjectLike}; -use crate::core::valid::Validator; use crate::core::Transform; /// NOTE: This is a bit of a boilerplate reducing module that is used in tests diff --git a/src/core/jit/request.rs b/src/core/jit/request.rs index 8bb59c9346..0caf3d4ee2 100644 --- a/src/core/jit/request.rs +++ b/src/core/jit/request.rs @@ -3,11 +3,11 @@ use std::ops::DerefMut; use async_graphql_value::ConstValue; use serde::Deserialize; +use tailcall_valid::Validator; use super::{transform, Builder, OperationPlan, Result, Variables}; use crate::core::blueprint::Blueprint; use crate::core::transform::TransformerOps; -use crate::core::valid::Validator; use crate::core::Transform; #[derive(Debug, Deserialize, Clone)] diff --git a/src/core/jit/synth/synth.rs b/src/core/jit/synth/synth.rs index 53b2234918..8a9e0043c0 100644 --- a/src/core/jit/synth/synth.rs +++ b/src/core/jit/synth/synth.rs @@ -239,6 +239,7 @@ where mod tests { use async_graphql_value::ConstValue; use serde::{Deserialize, Serialize}; + use tailcall_valid::Validator; use super::ValueStore; use crate::core::blueprint::Blueprint; @@ -250,7 +251,6 @@ mod tests { use crate::core::jit::synth::Synth; use crate::core::jit::OperationPlan; use crate::core::json::JsonLike; - use crate::core::valid::Validator; const POSTS: &str = r#" [ diff --git a/src/core/jit/transform/check_const.rs b/src/core/jit/transform/check_const.rs index fe7ebf427c..0db2ca1bf9 100644 --- a/src/core/jit/transform/check_const.rs +++ b/src/core/jit/transform/check_const.rs @@ -1,9 +1,10 @@ use std::convert::Infallible; use std::marker::PhantomData; +use tailcall_valid::Valid; + use crate::core::ir::model::IR; use crate::core::jit::OperationPlan; -use crate::core::valid::Valid; use crate::core::Transform; pub struct CheckConst(PhantomData); diff --git a/src/core/jit/transform/check_dedupe.rs b/src/core/jit/transform/check_dedupe.rs index b5f90ee5ad..e95be51434 100644 --- a/src/core/jit/transform/check_dedupe.rs +++ b/src/core/jit/transform/check_dedupe.rs @@ -1,8 +1,9 @@ use std::convert::Infallible; +use tailcall_valid::Valid; + use crate::core::ir::model::IR; use crate::core::jit::OperationPlan; -use crate::core::valid::Valid; use crate::core::Transform; pub struct CheckDedupe(std::marker::PhantomData); diff --git a/src/core/jit/transform/check_protected.rs b/src/core/jit/transform/check_protected.rs index 45394ba732..e55bbb3214 100644 --- a/src/core/jit/transform/check_protected.rs +++ b/src/core/jit/transform/check_protected.rs @@ -1,9 +1,10 @@ use std::convert::Infallible; use std::marker::PhantomData; +use tailcall_valid::Valid; + use crate::core::ir::model::IR; use crate::core::jit::OperationPlan; -use crate::core::valid::Valid; use crate::core::Transform; pub struct CheckProtected(PhantomData); diff --git a/src/core/jit/transform/skip.rs b/src/core/jit/transform/skip.rs index 0e89697755..0ecd315515 100644 --- a/src/core/jit/transform/skip.rs +++ b/src/core/jit/transform/skip.rs @@ -1,8 +1,9 @@ use std::marker::PhantomData; +use tailcall_valid::Valid; + use crate::core::jit::{Error, Field, OperationPlan, Variables}; use crate::core::json::JsonLike; -use crate::core::valid::Valid; use crate::core::Transform; pub struct Skip<'a, Var, Value> { diff --git a/src/core/json/json_schema.rs b/src/core/json/json_schema.rs index ff641a6efa..d07d5f287f 100644 --- a/src/core/json/json_schema.rs +++ b/src/core/json/json_schema.rs @@ -4,8 +4,7 @@ use std::fmt::Display; use convert_case::{Case, Casing}; use prost_reflect::{EnumDescriptor, FieldDescriptor, Kind, MessageDescriptor}; use serde::{Deserialize, Serialize}; - -use crate::core::valid::{Valid, Validator}; +use tailcall_valid::{Valid, Validator}; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema)] #[serde(rename = "schema")] @@ -241,7 +240,7 @@ impl JsonSchema { } impl TryFrom<&MessageDescriptor> for JsonSchema { - type Error = crate::core::valid::ValidationError; + type Error = tailcall_valid::ValidationError; fn try_from(value: &MessageDescriptor) -> Result { if value.is_map_entry() { @@ -270,7 +269,7 @@ impl TryFrom<&MessageDescriptor> for JsonSchema { } impl TryFrom<&EnumDescriptor> for JsonSchema { - type Error = crate::core::valid::ValidationError; + type Error = tailcall_valid::ValidationError; fn try_from(value: &EnumDescriptor) -> Result { let mut set = BTreeSet::new(); @@ -282,7 +281,7 @@ impl TryFrom<&EnumDescriptor> for JsonSchema { } impl TryFrom<&FieldDescriptor> for JsonSchema { - type Error = crate::core::valid::ValidationError; + type Error = tailcall_valid::ValidationError; fn try_from(value: &FieldDescriptor) -> Result { let field_schema = match value.kind() { @@ -331,12 +330,12 @@ mod tests { use indexmap::IndexMap; use pretty_assertions::assert_eq; use tailcall_fixtures::protobuf; + use tailcall_valid::{Valid, Validator}; use crate::core::blueprint::GrpcMethod; use crate::core::grpc::protobuf::tests::get_proto_file; use crate::core::grpc::protobuf::ProtobufSet; use crate::core::json::JsonSchema; - use crate::core::valid::{Valid, Validator}; #[test] fn test_validate_string() { diff --git a/src/core/mod.rs b/src/core/mod.rs index 4d6090c004..a7bde1484e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -39,7 +39,6 @@ mod serde_value_ext; pub mod tracing; mod transform; pub mod try_fold; -pub mod valid; pub mod variance; pub mod worker; pub mod wrapping_type; diff --git a/src/core/rest/endpoint_set.rs b/src/core/rest/endpoint_set.rs index 1c036a95d8..1d6042f327 100644 --- a/src/core/rest/endpoint_set.rs +++ b/src/core/rest/endpoint_set.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use tailcall_valid::Validator; + use super::endpoint::Endpoint; use super::partial_request::PartialRequest; use super::{Request, Result}; @@ -8,7 +10,6 @@ use crate::core::http::RequestContext; use crate::core::macros::MergeRight; use crate::core::rest::operation::OperationQuery; use crate::core::runtime::TargetRuntime; -use crate::core::valid::Validator; /// Collection of endpoints #[derive(Default, Clone, Debug, MergeRight)] diff --git a/src/core/rest/error.rs b/src/core/rest/error.rs index c23fda1aa7..1b37b991b7 100644 --- a/src/core/rest/error.rs +++ b/src/core/rest/error.rs @@ -5,8 +5,7 @@ use async_graphql::parser::types::{Directive, Type}; use async_graphql::{Name, ServerError}; use derive_more::{DebugCustom, From}; use serde_json; - -use crate::core::valid::ValidationError; +use tailcall_valid::ValidationError; #[derive(From, thiserror::Error, DebugCustom)] pub enum Error { diff --git a/src/core/rest/operation.rs b/src/core/rest/operation.rs index ff95a7670f..ea65a9f89a 100644 --- a/src/core/rest/operation.rs +++ b/src/core/rest/operation.rs @@ -1,12 +1,12 @@ use std::sync::Arc; use async_graphql::dynamic::Schema; +use tailcall_valid::{Cause, Valid, Validator}; use super::{Error, Result}; use crate::core::async_graphql_hyper::{GraphQLRequest, GraphQLRequestLike}; use crate::core::blueprint::{Blueprint, SchemaModifiers}; use crate::core::http::RequestContext; -use crate::core::valid::{Cause, Valid, Validator}; #[derive(Debug)] pub struct OperationQuery { diff --git a/src/core/transform.rs b/src/core/transform.rs index 969ffb93ee..1f68df5421 100644 --- a/src/core/transform.rs +++ b/src/core/transform.rs @@ -1,4 +1,4 @@ -use super::valid::{Valid, Validator}; +use tailcall_valid::{Valid, Validator}; /// A configuration transformer that allows us to perform various /// transformations on the configuration before it's further processed for diff --git a/src/core/try_fold.rs b/src/core/try_fold.rs index c8339c018b..949e7bd186 100644 --- a/src/core/try_fold.rs +++ b/src/core/try_fold.rs @@ -1,4 +1,4 @@ -use crate::core::valid::{Valid, Validator}; +use tailcall_valid::{Valid, Validator}; /// Trait for types that support a "try fold" operation. /// @@ -140,8 +140,9 @@ impl<'a, I, O: Clone, E> FromIterator> for TryFold<'a, I, O mod tests { use std::cell::RefCell; + use tailcall_valid::{Valid, ValidationError, Validator}; + use super::TryFold; - use crate::core::valid::{Valid, ValidationError, Validator}; impl<'a, I, O: Clone + 'a, E> TryFold<'a, I, O, E> { /// Create a `TryFold` that always succeeds with the provided state. diff --git a/src/core/valid/append.rs b/src/core/valid/append.rs deleted file mode 100644 index 884a4ca647..0000000000 --- a/src/core/valid/append.rs +++ /dev/null @@ -1,78 +0,0 @@ -pub trait Append { - type Out; - fn append(self, a: A) -> Self::Out; -} - -impl Append for (A0,) { - type Out = (A0, A1); - fn append(self, a1: A1) -> Self::Out { - let (a0,) = self; - (a0, a1) - } -} -impl Append for (A0, A1) { - type Out = (A0, A1, A2); - fn append(self, a2: A2) -> Self::Out { - let (a0, a1) = self; - (a0, a1, a2) - } -} -impl Append for (A0, A1, A2) { - type Out = (A0, A1, A2, A3); - fn append(self, a3: A3) -> Self::Out { - let (a0, a1, a2) = self; - (a0, a1, a2, a3) - } -} -impl Append for (A0, A1, A2, A3) { - type Out = (A0, A1, A2, A3, A4); - fn append(self, a4: A4) -> Self::Out { - let (a0, a1, a2, a3) = self; - (a0, a1, a2, a3, a4) - } -} -impl Append for (A0, A1, A2, A3, A4) { - type Out = (A0, A1, A2, A3, A4, A5); - fn append(self, a5: A5) -> Self::Out { - let (a0, a1, a2, a3, a4) = self; - (a0, a1, a2, a3, a4, a5) - } -} - -impl Append for (A0, A1, A2, A3, A4, A5) { - type Out = (A0, A1, A2, A3, A4, A5, A6); - fn append(self, a6: A6) -> Self::Out { - let (a0, a1, a2, a3, a4, a5) = self; - (a0, a1, a2, a3, a4, a5, a6) - } -} -impl Append for (A0, A1, A2, A3, A4, A5, A6) { - type Out = (A0, A1, A2, A3, A4, A5, A6, A7); - fn append(self, a7: A7) -> Self::Out { - let (a0, a1, a2, a3, a4, a5, a6) = self; - (a0, a1, a2, a3, a4, a5, a6, a7) - } -} -impl Append for (A0, A1, A2, A3, A4, A5, A6, A7) { - type Out = (A0, A1, A2, A3, A4, A5, A6, A7, A8); - fn append(self, a8: A8) -> Self::Out { - let (a0, a1, a2, a3, a4, a5, a6, a7) = self; - (a0, a1, a2, a3, a4, a5, a6, a7, a8) - } -} -impl Append for (A0, A1, A2, A3, A4, A5, A6, A7, A8) { - type Out = (A0, A1, A2, A3, A4, A5, A6, A7, A8, A9); - fn append(self, a9: A9) -> Self::Out { - let (a0, a1, a2, a3, a4, a5, a6, a7, a8) = self; - (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) - } -} -impl Append - for (A0, A1, A2, A3, A4, A5, A6, A7, A8, A9) -{ - type Out = (A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); - fn append(self, a10: A10) -> Self::Out { - let (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) = self; - (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) - } -} diff --git a/src/core/valid/cause.rs b/src/core/valid/cause.rs deleted file mode 100644 index 5cea784953..0000000000 --- a/src/core/valid/cause.rs +++ /dev/null @@ -1,65 +0,0 @@ -use std::collections::VecDeque; -use std::fmt::Display; - -use derive_setters::Setters; -use thiserror::Error; - -#[derive(Clone, PartialEq, Debug, Setters, Error)] -pub struct Cause { - pub message: E, - #[setters(strip_option)] - pub description: Option, - #[setters(skip)] - pub trace: VecDeque, -} - -impl Display for Cause { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "[")?; - for (i, entry) in self.trace.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - write!(f, "{}", entry)?; - } - write!(f, "] {}", self.message)?; - if let Some(desc) = self.description.as_ref() { - write!(f, ": {}", desc)?; - } - Ok(()) - } -} - -impl Cause { - pub fn new(e: E) -> Self { - Cause { message: e, description: None, trace: VecDeque::new() } - } - - pub fn transform(self, e: impl Fn(E) -> E1) -> Cause { - Cause { - message: e(self.message), - description: self.description.map(e), - trace: self.trace, - } - } - - pub fn trace(mut self, trace: Vec) -> Self { - self.trace = trace - .iter() - .map(|t| t.to_string()) - .collect::>(); - self - } -} - -#[cfg(test)] -mod tests { - #[test] - fn test_display() { - use super::Cause; - let cause = Cause::new("error") - .trace(vec!["trace0", "trace1"]) - .description("description"); - assert_eq!(cause.to_string(), "[trace0, trace1] error: description"); - } -} diff --git a/src/core/valid/error.rs b/src/core/valid/error.rs deleted file mode 100644 index d4350f1d7a..0000000000 --- a/src/core/valid/error.rs +++ /dev/null @@ -1,174 +0,0 @@ -use std::fmt::{Debug, Display}; - -use regex::Regex; - -use super::Cause; - -#[derive(Debug, PartialEq, Default, Clone)] -pub struct ValidationError(Vec>); - -impl Display for ValidationError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("Validation Error\n")?; - let errors = self.as_vec(); - for error in errors { - f.write_str(format!("{} {}", '\u{2022}', error.message).as_str())?; - if !error.trace.is_empty() { - f.write_str( - &(format!( - " [{}]", - error - .trace - .iter() - .cloned() - .collect::>() - .join(", ") - )), - )?; - } - f.write_str("\n")?; - } - - Ok(()) - } -} - -impl ValidationError { - pub fn as_vec(&self) -> &Vec> { - &self.0 - } - - pub fn combine(mut self, mut other: ValidationError) -> ValidationError { - self.0.append(&mut other.0); - self - } - - pub fn empty() -> Self { - ValidationError(Vec::new()) - } - - pub fn new(e: E) -> Self { - ValidationError(vec![Cause::new(e)]) - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - pub fn trace(self, message: &str) -> Self { - let mut errors = self.0; - for cause in errors.iter_mut() { - cause.trace.insert(0, message.to_owned()); - } - Self(errors) - } - - pub fn append(self, error: E) -> Self { - let mut errors = self.0; - errors.push(Cause::new(error)); - Self(errors) - } - - pub fn transform(self, f: &impl Fn(E) -> E1) -> ValidationError { - ValidationError(self.0.into_iter().map(|cause| cause.transform(f)).collect()) - } -} - -impl std::error::Error for ValidationError {} - -impl From> for ValidationError { - fn from(value: Cause) -> Self { - ValidationError(vec![value]) - } -} - -impl From>> for ValidationError { - fn from(value: Vec>) -> Self { - ValidationError(value) - } -} - -impl From> for ValidationError { - fn from(error: serde_path_to_error::Error) -> Self { - let mut trace = Vec::new(); - let segments = error.path().iter(); - let len = segments.len(); - for (i, segment) in segments.enumerate() { - match segment { - serde_path_to_error::Segment::Seq { index } => { - trace.push(format!("[{}]", index)); - } - serde_path_to_error::Segment::Map { key } => { - trace.push(key.to_string()); - } - serde_path_to_error::Segment::Enum { variant } => { - trace.push(variant.to_string()); - } - serde_path_to_error::Segment::Unknown => { - trace.push("?".to_owned()); - } - } - if i < len - 1 { - trace.push(".".to_owned()); - } - } - - let re = Regex::new(r" at line \d+ column \d+$").unwrap(); - let message = re - .replace( - format!("Parsing failed because of {}", error.inner()).as_str(), - "", - ) - .into_owned(); - - ValidationError(vec![Cause::new(message).trace(trace)]) - } -} - -impl From for ValidationError { - fn from(error: http::header::InvalidHeaderValue) -> Self { - ValidationError::new(error.to_string()) - } -} - -#[cfg(test)] -mod tests { - use pretty_assertions::assert_eq; - use stripmargin::StripMargin; - - use crate::core::valid::{Cause, ValidationError}; - - #[derive(Debug, PartialEq, serde::Deserialize)] - struct Foo { - a: i32, - } - - #[test] - fn test_error_display_formatting() { - let error = ValidationError::from(vec![ - Cause::new("1").trace(vec!["a", "b"]), - Cause::new("2"), - Cause::new("3"), - ]); - let expected_output = "\ - |Validation Error - |• 1 [a, b] - |• 2 - |• 3 - |" - .strip_margin(); - assert_eq!(format!("{}", error), expected_output); - } - - #[test] - fn test_from_serde_error() { - let foo = &mut serde_json::Deserializer::from_str("{ \"a\": true }"); - let actual = - ValidationError::from(serde_path_to_error::deserialize::<_, Foo>(foo).unwrap_err()); - let expected = ValidationError::new( - "Parsing failed because of invalid type: boolean `true`, expected i32".to_string(), - ) - .trace("a"); - assert_eq!(actual, expected); - } -} diff --git a/src/core/valid/mod.rs b/src/core/valid/mod.rs deleted file mode 100644 index 1491d70319..0000000000 --- a/src/core/valid/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -mod append; -mod cause; -mod error; -mod valid; - -pub use cause::*; -pub use error::*; -pub use valid::*; - -/// Moral equivalent of TryFrom for validation purposes -pub trait ValidateFrom: Sized { - type Error; - fn validate_from(a: T) -> Valid; -} - -/// Moral equivalent of TryInto for validation purposes -pub trait ValidateInto { - type Error; - fn validate_into(self) -> Valid; -} - -/// A blanket implementation for ValidateInto -impl> ValidateInto for S { - type Error = T::Error; - - fn validate_into(self) -> Valid { - T::validate_from(self) - } -} diff --git a/src/core/valid/valid.rs b/src/core/valid/valid.rs deleted file mode 100644 index cda47c82db..0000000000 --- a/src/core/valid/valid.rs +++ /dev/null @@ -1,386 +0,0 @@ -use super::append::Append; -use super::ValidationError; -use crate::core::valid::Cause; - -#[derive(Debug, PartialEq)] -pub struct Valid(Result>); - -pub trait Validator: Sized { - fn map(self, f: impl FnOnce(A) -> A1) -> Valid { - Valid(self.to_result().map(f)) - } - - fn foreach(self, mut f: impl FnMut(A)) -> Valid - where - A: Clone, - { - match self.to_result() { - Ok(a) => { - f(a.clone()); - Valid::succeed(a) - } - Err(e) => Valid(Err(e)), - } - } - - fn is_succeed(&self) -> bool; - - fn is_fail(&self) -> bool; - - fn and(self, other: Valid) -> Valid { - self.zip(other).map(|(_, a1)| a1) - } - - fn zip(self, other: Valid) -> Valid<(A, A1), E> { - match self.to_result() { - Ok(a) => match other.0 { - Ok(a1) => Valid(Ok((a, a1))), - Err(e1) => Valid(Err(e1)), - }, - Err(e1) => match other.0 { - Ok(_) => Valid(Err(e1)), - Err(e2) => Valid(Err(e1.combine(e2))), - }, - } - } - - fn fuse(self, other: Valid) -> Fusion<(A, A1), E> { - Fusion(self.zip(other)) - } - - fn trace(self, message: &str) -> Valid { - let valid = self.to_result(); - if let Err(error) = valid { - return Valid(Err(error.trace(message))); - } - - Valid(valid) - } - - fn fold( - self, - ok: impl FnOnce(A) -> Valid, - err: impl FnOnce() -> Valid, - ) -> Valid { - match self.to_result() { - Ok(a) => ok(a), - Err(e) => Valid::(Err(e)).and(err()), - } - } - - fn to_result(self) -> Result>; - - fn and_then(self, f: impl FnOnce(A) -> Valid) -> Valid { - match self.to_result() { - Ok(a) => f(a), - Err(e) => Valid(Err(e)), - } - } - - fn unit(self) -> Valid<(), E> { - self.map(|_| ()) - } - - fn some(self) -> Valid, E> { - self.map(Some) - } - - fn map_to(self, b: B) -> Valid { - self.map(|_| b) - } - fn when(self, f: impl FnOnce() -> bool) -> Valid<(), E> { - if f() { - self.unit() - } else { - Valid::succeed(()) - } - } -} - -impl Valid { - pub fn fail(e: E) -> Valid { - Valid(Err((vec![Cause::new(e)]).into())) - } - - pub fn fail_with(message: E, description: E) -> Valid - where - E: std::fmt::Debug, - { - Valid(Err( - (vec![Cause::new(message).description(description)]).into() - )) - } - - pub fn from_validation_err(error: ValidationError) -> Self { - Valid(Err(error)) - } - - pub fn from_vec_cause(error: Vec>) -> Self { - Valid(Err(error.into())) - } - - pub fn succeed(a: A) -> Valid { - Valid(Ok(a)) - } - - pub fn from_iter( - iter: impl IntoIterator, - mut f: impl FnMut(A) -> Valid, - ) -> Valid, E> { - let mut values: Vec = Vec::new(); - let mut errors: ValidationError = ValidationError::empty(); - for a in iter.into_iter() { - match f(a).to_result() { - Ok(b) => { - values.push(b); - } - Err(err) => { - errors = errors.combine(err); - } - } - } - - if errors.is_empty() { - Valid::succeed(values) - } else { - Valid::from_validation_err(errors) - } - } - - pub fn from_option(option: Option, e: E) -> Valid { - match option { - Some(a) => Valid::succeed(a), - None => Valid::fail(e), - } - } - - pub fn none() -> Valid, E> { - Valid::succeed(None) - } -} - -impl Validator for Valid { - fn to_result(self) -> Result> { - self.0 - } - - fn is_succeed(&self) -> bool { - self.0.is_ok() - } - - fn is_fail(&self) -> bool { - self.0.is_err() - } -} - -pub struct Fusion(Valid); -impl Fusion { - pub fn fuse(self, other: Valid) -> Fusion - where - A: Append, - { - Fusion(self.0.zip(other).map(|(a, a1)| a.append(a1))) - } -} - -impl Validator for Fusion { - fn to_result(self) -> Result> { - self.0.to_result() - } - fn is_succeed(&self) -> bool { - self.0.is_succeed() - } - fn is_fail(&self) -> bool { - self.0.is_fail() - } -} - -impl From>> for Valid { - fn from(value: Result>) -> Self { - match value { - Ok(a) => Valid::succeed(a), - Err(e) => Valid::from_validation_err(e), - } - } -} - -impl From> for Valid { - fn from(value: Fusion) -> Self { - Valid(value.to_result()) - } -} - -impl Clone for Valid -where - A: Clone, - E: Clone, -{ - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - -#[cfg(test)] -mod tests { - use super::{Cause, ValidationError}; - use crate::core::valid::valid::Valid; - use crate::core::valid::Validator; - - #[test] - fn test_ok() { - let result = Valid::::succeed(1); - assert_eq!(result, Valid::succeed(1)); - } - - #[test] - fn test_fail() { - let result = Valid::<(), i32>::fail(1); - assert_eq!(result, Valid::fail(1)); - } - - #[test] - fn test_validate_or_both_ok() { - let result1 = Valid::::succeed(true); - let result2 = Valid::::succeed(3); - - assert_eq!(result1.and(result2), Valid::succeed(3u8)); - } - - #[test] - fn test_validate_or_first_fail() { - let result1 = Valid::::fail(-1); - let result2 = Valid::::succeed(3); - - assert_eq!(result1.and(result2), Valid::fail(-1)); - } - - #[test] - fn test_validate_or_second_fail() { - let result1 = Valid::::succeed(true); - let result2 = Valid::::fail(-2); - - assert_eq!(result1.and(result2), Valid::fail(-2)); - } - - #[test] - fn test_validate_all() { - let input: Vec = [1, 2, 3].to_vec(); - let result: Valid, i32> = Valid::from_iter(input, |a| Valid::fail(a * 2)); - assert_eq!( - result, - Valid::from_vec_cause(vec![Cause::new(2), Cause::new(4), Cause::new(6)]) - ); - } - - #[test] - fn test_validate_all_ques() { - let input: Vec = [1, 2, 3].to_vec(); - let result: Valid, i32> = Valid::from_iter(input, |a| Valid::fail(a * 2)); - assert_eq!( - result, - Valid::from_vec_cause(vec![Cause::new(2), Cause::new(4), Cause::new(6)]) - ); - } - - #[test] - fn test_ok_ok_cause() { - let option: Option = None; - let result = Valid::from_option(option, 1); - assert_eq!(result, Valid::from_vec_cause(vec![Cause::new(1)])); - } - - #[test] - fn test_trace() { - let result = Valid::<(), i32>::fail(1).trace("A").trace("B").trace("C"); - let expected = Valid::from_vec_cause(vec![Cause { - message: 1, - description: None, - trace: vec!["C".to_string(), "B".to_string(), "A".to_string()].into(), - }]); - assert_eq!(result, expected); - } - - #[test] - fn test_validate_fold_err() { - let valid = Valid::<(), i32>::fail(1); - let result = valid.fold(|_| Valid::<(), i32>::fail(2), || Valid::<(), i32>::fail(3)); - assert_eq!( - result, - Valid::from_vec_cause(vec![Cause::new(1), Cause::new(3)]) - ); - } - - #[test] - fn test_validate_fold_ok() { - let valid = Valid::::succeed(1); - let result = valid.fold(Valid::::fail, || Valid::::fail(2)); - assert_eq!(result, Valid::fail(1)); - } - - #[test] - fn test_to_result() { - let result = Valid::<(), i32>::fail(1).to_result().unwrap_err(); - assert_eq!(result, ValidationError::new(1)); - } - - #[test] - fn test_validate_both_ok() { - let result1 = Valid::::succeed(true); - let result2 = Valid::::succeed(3); - - assert_eq!(result1.zip(result2), Valid::succeed((true, 3u8))); - } - #[test] - fn test_validate_both_first_fail() { - let result1 = Valid::::fail(-1); - let result2 = Valid::::succeed(3); - - assert_eq!(result1.zip(result2), Valid::fail(-1)); - } - #[test] - fn test_validate_both_second_fail() { - let result1 = Valid::::succeed(true); - let result2 = Valid::::fail(-2); - - assert_eq!(result1.zip(result2), Valid::fail(-2)); - } - - #[test] - fn test_validate_both_both_fail() { - let result1 = Valid::::fail(-1); - let result2 = Valid::::fail(-2); - - assert_eq!( - result1.zip(result2), - Valid::from_vec_cause(vec![Cause::new(-1), Cause::new(-2)]) - ); - } - - #[test] - fn test_and_then_success() { - let result = Valid::::succeed(1).and_then(|a| Valid::succeed(a + 1)); - assert_eq!(result, Valid::succeed(2)); - } - - #[test] - fn test_and_then_fail() { - let result = Valid::::succeed(1).and_then(|a| Valid::::fail(a + 1)); - assert_eq!(result, Valid::fail(2)); - } - - #[test] - fn test_foreach_succeed() { - let mut a = 0; - let result = Valid::::succeed(1).foreach(|v| a = v); - assert_eq!(result, Valid::succeed(1)); - assert_eq!(a, 1); - } - - #[test] - fn test_foreach_fail() { - let mut a = 0; - let result = Valid::::fail(1).foreach(|v| a = v); - assert_eq!(result, Valid::fail(1)); - assert_eq!(a, 0); - } -} diff --git a/src/core/variance.rs b/src/core/variance.rs index f4c809b521..e45f38384d 100644 --- a/src/core/variance.rs +++ b/src/core/variance.rs @@ -1,6 +1,7 @@ +use tailcall_valid::Valid; + use crate::core::merge_right::MergeRight; use crate::core::primitive::Primitive; -use crate::core::valid::Valid; /// A trait representing types that are **invariant** with respect to merging /// operations. diff --git a/tailcall-wasm/Cargo.toml b/tailcall-wasm/Cargo.toml index e007c50624..36a222831d 100644 --- a/tailcall-wasm/Cargo.toml +++ b/tailcall-wasm/Cargo.toml @@ -24,6 +24,7 @@ async-graphql-value = "7.0.5" serde_json = "1.0.117" url = "2.5.0" http = { workspace = true } +tailcall-valid = { workspace = true } [dev-dependencies] wasm-bindgen-test = "0.3.42" diff --git a/tailcall-wasm/src/builder.rs b/tailcall-wasm/src/builder.rs index df30b7d739..e35ea83442 100644 --- a/tailcall-wasm/src/builder.rs +++ b/tailcall-wasm/src/builder.rs @@ -7,8 +7,8 @@ use tailcall::core::config::ConfigModule; use tailcall::core::merge_right::MergeRight; use tailcall::core::rest::EndpointSet; use tailcall::core::runtime::TargetRuntime; -use tailcall::core::valid::Validator; use tailcall::core::variance::Invariant; +use tailcall_valid::Validator; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; diff --git a/tests/cli/gen.rs b/tests/cli/gen.rs index 030ff69c40..4fe29d8a3e 100644 --- a/tests/cli/gen.rs +++ b/tests/cli/gen.rs @@ -279,7 +279,7 @@ pub mod test { use tailcall::core::blueprint::Blueprint; use tailcall::core::config::{self, ConfigModule}; use tailcall::core::generator::Generator as ConfigGenerator; - use tailcall::core::valid::{ValidateInto, Validator}; + use tailcall_valid::{ValidateInto, Validator}; use super::http::NativeHttpTest; use crate::env::Env; diff --git a/tests/core/spec.rs b/tests/core/spec.rs index b69499b57f..1a0099eb0b 100644 --- a/tests/core/spec.rs +++ b/tests/core/spec.rs @@ -19,9 +19,9 @@ use tailcall::core::config::transformer::Required; use tailcall::core::config::{Config, ConfigModule, Source}; use tailcall::core::http::handle_request; use tailcall::core::print_schema::print_schema; -use tailcall::core::valid::{Cause, Valid, ValidationError, Validator}; use tailcall::core::variance::Invariant; use tailcall_prettier::Parser; +use tailcall_valid::{Cause, Valid, ValidationError, Validator}; use super::file::File; use super::http::Http; diff --git a/tests/jit_spec.rs b/tests/jit_spec.rs index 01b2d5bb21..0cd80fc5a0 100644 --- a/tests/jit_spec.rs +++ b/tests/jit_spec.rs @@ -14,7 +14,7 @@ mod tests { }; use tailcall::core::json::{JsonLike, JsonObjectLike}; use tailcall::core::rest::EndpointSet; - use tailcall::core::valid::Validator; + use tailcall_valid::Validator; struct TestExecutor { app_ctx: Arc,