diff --git a/typegraph/core/src/runtimes/mod.rs b/typegraph/core/src/runtimes/mod.rs index e13ecada5b..378b108e72 100644 --- a/typegraph/core/src/runtimes/mod.rs +++ b/typegraph/core/src/runtimes/mod.rs @@ -21,6 +21,7 @@ use crate::runtimes::prisma::migration::{ }; use crate::runtimes::prisma::with_prisma_runtime; use crate::runtimes::typegraph::TypegraphOperation; +use crate::t::TypeBuilder; use crate::validation::types::validate_value; use crate::wit::aws::S3RuntimeData; use crate::wit::core::{FuncParams, MaterializerId, RuntimeId, TypeId as CoreTypeId}; diff --git a/typegraph/core/src/runtimes/prisma/relationship/mod.rs b/typegraph/core/src/runtimes/prisma/relationship/mod.rs index 17e0709b21..1eddfe6fb6 100644 --- a/typegraph/core/src/runtimes/prisma/relationship/mod.rs +++ b/typegraph/core/src/runtimes/prisma/relationship/mod.rs @@ -115,7 +115,7 @@ impl Relationship { } } -#[derive(Default)] +#[derive(Default, Clone)] pub struct PrismaLink { type_name: String, rel_name: Option, @@ -145,15 +145,15 @@ impl PrismaLink { self } - pub fn build(mut self) -> Result { - let mut proxy = t::proxy(self.type_name); - if let Some(rel_name) = self.rel_name.take() { + fn build_link(&self) -> Result { + let mut proxy = t::proxy(&self.type_name); + if let Some(rel_name) = self.rel_name.clone() { proxy.set("rel_name", rel_name); } if let Some(fkey) = self.fkey { proxy.set("fkey", format!("{fkey}")); } - if let Some(target_field) = self.target_field.take() { + if let Some(target_field) = self.target_field.clone() { proxy.set("target_field", target_field); } let res = proxy.build()?; @@ -162,6 +162,17 @@ impl PrismaLink { } } +impl TypeBuilder for PrismaLink { + fn build(&self) -> Result { + self.build_link() + } +} + +#[allow(dead_code)] +pub fn prisma_linkx(typ: impl TypeBuilder) -> Result { + prisma_link(typ.build()?) +} + pub fn prisma_link(type_id: TypeId) -> Result { let name = type_id .type_name()? @@ -180,11 +191,10 @@ use registry::RelationshipRegistry; #[cfg(test)] mod test { - use super::prisma_linkn; + use super::{prisma_linkn, prisma_linkx}; use crate::errors::Result; use crate::global_store::Store; use crate::runtimes::prisma::errors; - use crate::runtimes::prisma::relationship::prisma_link; use crate::runtimes::prisma::relationship::registry::RelationshipRegistry; use crate::t::{self, ConcreteTypeBuilder, TypeBuilder}; use crate::test_utils::*; @@ -205,16 +215,16 @@ mod test { fn test_explicit_relationship_name() -> Result<(), String> { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("name", t::string().build()?) - .prop("posts", t::array(t::proxy("Post").build()?).build()?) + .propx("id", t::integer().as_id(true))? + .propx("name", t::string())? + .propx("posts", t::arrayx(t::proxy("Post"))?)? .named("User") .build()?; let post = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("title", t::string().build()?) - .prop("author", prisma_linkn("User").name("PostAuthor").build()?) + .propx("id", t::integer().as_id(true))? + .propx("title", t::string())? + .propx("author", prisma_linkn("User").name("PostAuthor"))? .named("Post") .build()?; @@ -231,19 +241,17 @@ mod test { fn test_fkey_attribute() -> Result<(), String> { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop( + .propx("id", t::integer().as_id(true))? + .propx( "profile", - prisma_link(t::optional(t::proxy("Profile").build()?).build()?)? - .fkey(true) - .build()?, - ) + prisma_linkx(t::optionalx(t::proxy("Profile"))?)?.fkey(true), + )? .named("User") .build()?; let profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("user", t::optional(t::proxy("User").build()?).build()?) + .propx("id", t::integer().as_id(true))? + .propx("user", t::optionalx(t::proxy("User"))?)? .named("Profile") .build()?; @@ -260,19 +268,17 @@ mod test { fn test_unique_attribute() -> Result<(), String> { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop( + .propx("id", t::integer().as_id(true))? + .propx( "profile", - t::optional(t::proxy("Profile").build()?) - .config("unique", "true") - .build()?, - ) + t::optionalx(t::proxy("Profile"))?.config("unique", "true"), + )? .named("User") .build()?; let profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("user", t::optional(t::proxy("User").build()?).build()?) + .propx("id", t::integer().as_id(true))? + .propx("user", t::optionalx(t::proxy("User"))?)? .named("Profile") .build()?; @@ -289,9 +295,9 @@ mod test { fn test_self_relationship() -> Result<(), String> { Store::reset(); let node = t::struct_() - .prop("id", t::string().as_id(true).build()?) - .prop("children", t::array(t::proxy("Node").build()?).build()?) - .prop("parent", t::proxy("Node").build()?) + .propx("id", t::string().as_id(true))? + .propx("children", t::arrayx(t::proxy("Node"))?)? + .propx("parent", t::proxy("Node"))? .named("Node") .build()?; @@ -307,14 +313,14 @@ mod test { fn test_ambiguous_side() -> Result<(), String> { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("profile", t::proxy("Profile").build()?) + .propx("id", t::integer().as_id(true))? + .propx("profile", t::proxy("Profile"))? .named("User") .build()?; let profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("user", t::proxy("User").build()?) + .propx("id", t::integer().as_id(true))? + .propx("user", t::proxy("User"))? .named("Profile") .build()?; @@ -332,17 +338,14 @@ mod test { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop( - "profile", - t::optional(t::proxy("Profile").build()?).build()?, - ) + .propx("id", t::integer().as_id(true))? + .propx("profile", t::optionalx(t::proxy("Profile"))?)? .named("User") .build()?; let profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("user", t::optional(t::proxy("User").build()?).build()?) + .propx("id", t::integer().as_id(true))? + .propx("user", t::optionalx(t::proxy("User"))?)? .named("Profile") .build()?; @@ -365,14 +368,14 @@ mod test { fn test_conflicting_attributes() -> Result<(), String> { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("profile", prisma_linkn("Profile").fkey(true).build()?) + .propx("id", t::integer().as_id(true))? + .propx("profile", prisma_linkn("Profile").fkey(true))? .named("User") .build()?; let profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("user", prisma_linkn("User").fkey(true).build()?) + .propx("id", t::integer().as_id(true))? + .propx("user", prisma_linkn("User").fkey(true))? .named("Profile") .build()?; @@ -394,14 +397,14 @@ mod test { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("profile", prisma_linkn("Profile").fkey(false).build()?) + .propx("id", t::integer().as_id(true))? + .propx("profile", prisma_linkn("Profile").fkey(false))? .named("User") .build()?; let profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("user", prisma_linkn("User").fkey(false).build()?) + .propx("id", t::integer().as_id(true))? + .propx("user", prisma_linkn("User").fkey(false))? .named("Profile") .build()?; @@ -428,13 +431,13 @@ mod test { fn test_missing_target() -> Result<(), String> { Store::reset(); let user = t::struct_() - .prop("id", t::integer().as_id(true).build()?) - .prop("profile", prisma_linkn("Profile").fkey(true).build()?) + .propx("id", t::integer().as_id(true))? + .propx("profile", prisma_linkn("Profile").fkey(true))? .named("User") .build()?; let _profile = t::struct_() - .prop("id", t::integer().as_id(true).build()?) + .propx("id", t::integer().as_id(true))? .named("Profile") .build()?; diff --git a/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs b/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs index fe5faa2a69..3d7d30dbc9 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs @@ -41,7 +41,7 @@ impl TypeGen for Distinct { .map(|(k, _)| k.to_string()) .collect::>(); - t::array(t::string().enum_(cols).build()?) + t::arrayx(t::string().enum_(cols))? .named(self.name()) .build() } diff --git a/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs b/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs index 5d6448f044..3d2be9f7e0 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs @@ -22,7 +22,7 @@ impl CountOutput { impl TypeGen for CountOutput { fn generate(&self, _context: &mut TypeGenContext) -> Result { let mut builder = t::struct_(); - let opt_int = t::optional(t::integer().build()?).build()?; + let opt_int = t::optionalx(t::integer())?.build()?; builder.prop("_all", opt_int); for (k, _) in self.model_id.as_struct()?.iter_props() { @@ -54,11 +54,11 @@ impl TypeGen for NumberAggregateOutput { fn generate(&self, _context: &mut TypeGenContext) -> Result { let mut builder = t::struct_(); - let opt_float = t::optional(t::float().build()?).build()?; + let opt_float = t::optionalx(t::float())?.build()?; let for_int = if self.avg { opt_float } else { - t::optional(t::integer().build()?).build()? + t::optionalx(t::integer())?.build()? }; for (k, type_id) in self.model_id.as_struct()?.iter_props() { diff --git a/typegraph/core/src/runtimes/prisma/type_generation/count.rs b/typegraph/core/src/runtimes/prisma/type_generation/count.rs index 59e2ae5d18..0023670bd7 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/count.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/count.rs @@ -13,9 +13,7 @@ pub struct Count; impl TypeGen for Count { fn generate(&self, _context: &mut TypeGenContext) -> Result { - t::optional(t::integer().build()?) - .named(self.name()) - .build() + t::optionalx(t::integer())?.named(self.name()).build() } fn name(&self) -> String { diff --git a/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs b/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs index 6cb4fbe76f..46d64b58c2 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs @@ -42,7 +42,7 @@ impl TypeGen for GroupingFields { } } - t::array(t::string().enum_(fields).build()?) + t::arrayx(t::string().enum_(fields))? .named(self.name()) .build() } @@ -73,16 +73,12 @@ impl TypeGen for Having { let name = self.name(); let self_ref = t::proxy(&name).build()?; - t::union([ + t::unionx![ extended_type, - t::struct_() - .prop("AND", t::array(self_ref).build()?) - .build()?, - t::struct_() - .prop("OR", t::array(self_ref).build()?) - .build()?, - t::struct_().prop("NOT", self_ref).build()?, - ]) + t::struct_().propx("AND", t::array(self_ref))?, + t::struct_().propx("OR", t::array(self_ref))?, + t::struct_().prop("NOT", self_ref) + ] .named(name) .build() } diff --git a/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs b/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs index 5cc2d67428..83cba52ae6 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs @@ -74,18 +74,18 @@ impl TypeGen for InputType { let connect = context.generate(&Where::new(entry.model_type, false))?; let mut inner = t::struct_(); - inner.prop("create", t::optional(create).build()?); - inner.prop("connect", t::optional(connect).build()?); + inner.propx("create", t::optional(create))?; + inner.propx("connect", t::optional(connect))?; if let Cardinality::Many = entry.cardinality { - let create_many = t::struct_() - .prop("data", t::array(create).build()?) - .build()?; - inner.prop("createMany", t::optional(create_many).build()?); + inner.propx( + "createMany", + t::optionalx(t::struct_().propx("data", t::array(create))?)?, + )?; } // TODO what if cardinality is Cardinality::One ?? - builder.prop(k, t::optional(inner.min(1).max(1).build()?).build()?); + builder.propx(k, t::optionalx(inner.min(1).max(1))?)?; } else { let attrs = type_id.attrs()?; match attrs.concrete_type.as_type()? { diff --git a/typegraph/core/src/runtimes/prisma/type_generation/mod.rs b/typegraph/core/src/runtimes/prisma/type_generation/mod.rs index f9f867a65c..459ef95305 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/mod.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/mod.rs @@ -104,10 +104,10 @@ impl TypeGenContext { Ok(OperationTypes { input: t::struct_() - .prop( + .propx( "where", - t::optional(self.generate(&QueryUniqueWhereExpr::new(model_id))?).build()?, - ) + t::optional(self.generate(&QueryUniqueWhereExpr::new(model_id))?), + )? .build()?, output: t::optional(self.generate(&WithNestedCount::new(model_id))?).build()?, }) @@ -194,13 +194,13 @@ impl TypeGenContext { Ok(OperationTypes { input: t::struct_() - .prop( + .propx( "data", - t::array(self.generate(&InputType::for_create(model_id))?).build()?, - ) + t::array(self.generate(&InputType::for_create(model_id))?), + )? .build()?, // TODO typegen: BatchOutput - output: t::struct_().prop("count", t::integer().build()?).build()?, + output: t::struct_().propx("count", t::integer())?.build()?, }) } @@ -230,7 +230,7 @@ impl TypeGenContext { t::optional(self.generate(&QueryWhereExpr::new(model_id))?).build()?, ) .build()?, - output: t::struct_().prop("count", t::integer().build()?).build()?, + output: t::struct_().propx("count", t::integer())?.build()?, }) } @@ -273,7 +273,7 @@ impl TypeGenContext { t::optional(self.generate(&QueryWhereExpr::new(model_id))?).build()?, ) .build()?, - output: t::struct_().prop("count", t::integer().build()?).build()?, + output: t::struct_().propx("count", t::integer())?.build()?, }) } diff --git a/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs b/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs index f11857eee2..671c6abbfb 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs @@ -72,7 +72,7 @@ impl TypeGen for OrderBy { let inner = context.generate( &OrderBy::new(relationship_model.model_type).skip(skip_rel), )?; - builder.prop(k, t::optional(inner).build()?); + builder.propx(k, t::optional(inner))?; } } } else { @@ -92,7 +92,7 @@ impl TypeGen for OrderBy { } } - t::array(builder.build()?).named(self.name()).build() + t::arrayx(builder)?.named(self.name()).build() } fn name(&self) -> String { @@ -155,7 +155,7 @@ impl TypeGen for Sort { builder.prop("nulls", nulls_order); } - t::optional(t::union([builder.build()?, sort_order]).build()?) + t::optionalx(t::unionx![builder, sort_order])? .named(self.name()) .build() } @@ -178,7 +178,7 @@ impl TypeGen for SortByAggregates { builder.prop("_min", sort); builder.prop("_max", sort); - t::optional(builder.build()?).named(self.name()).build() + t::optionalx(builder)?.named(self.name()).build() } fn name(&self) -> String { @@ -230,23 +230,17 @@ impl TypeGen for AggregateSorting { .collect::>>()?; let mut builder = t::struct_(); - let count = t::optional( - t::struct_from(props.iter().filter_map(|p| { - p.generate(context, true) - .unwrap() - .map(|ty| (p.key.clone(), ty)) - })) - .build()?, - ) + let count = t::optionalx(t::struct_from(props.iter().filter_map(|p| { + p.generate(context, true) + .unwrap() + .map(|ty| (p.key.clone(), ty)) + })))? .build()?; - let others = t::optional( - t::struct_from(props.iter().filter_map(|p| { - p.generate(context, false) - .unwrap() - .map(|ty| (p.key.clone(), ty)) - })) - .build()?, - ) + let others = t::optionalx(t::struct_from(props.iter().filter_map(|p| { + p.generate(context, false) + .unwrap() + .map(|ty| (p.key.clone(), ty)) + })))? .build()?; builder .prop("_count", count) diff --git a/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs b/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs index 6a40379609..9bca176152 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs @@ -42,29 +42,26 @@ impl TypeGen for QueryInputType { }; builder - .prop( + .propx( "where", - t::optional(context.generate(&QueryWhereExpr::new(self.model_id))?).build()?, - ) - .prop( - "orderBy", - t::optional(context.generate(&order_by)?).build()?, - ) - .prop("take", t::optional(context.generate(&Take)?).build()?) - .prop("skip", t::optional(context.generate(&Skip)?).build()?); + t::optional(context.generate(&QueryWhereExpr::new(self.model_id))?), + )? + .propx("orderBy", t::optional(context.generate(&order_by)?))? + .propx("take", t::optional(context.generate(&Take)?))? + .propx("skip", t::optional(context.generate(&Skip)?))?; if self.is_group_by { builder.prop("by", context.generate(&GroupingFields::new(self.model_id))?); - builder.prop( + builder.propx( "having", // t::optional(context.generate(&Having::new(self.model_id))?).build()?, - t::optional(context.generate(&Having::new(self.model_id))?).build()?, - ); + t::optional(context.generate(&Having::new(self.model_id))?), + )?; } else { - builder.prop( + builder.propx( "distinct", - t::optional(context.generate(&Distinct(self.model_id))?).build()?, - ); + t::optional(context.generate(&Distinct(self.model_id))?), + )?; } builder.named(self.name()).build() diff --git a/typegraph/core/src/runtimes/prisma/type_generation/query_unique_where_expr.rs b/typegraph/core/src/runtimes/prisma/type_generation/query_unique_where_expr.rs index 476707973c..df65808f70 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/query_unique_where_expr.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/query_unique_where_expr.rs @@ -43,7 +43,7 @@ impl TypeGen for QueryUniqueWhereExpr { continue; } let inner = attrs.concrete_type.resolve_quant()?; - builder.prop(key, t::optional(inner).build()?); + builder.propx(key, t::optional(inner))?; } builder.named(self.name()).build() diff --git a/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs b/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs index 02d2e2b9ad..e7268f0549 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs @@ -26,7 +26,7 @@ impl TypeGen for QueryWhereExpr { let name = self.name(); let self_ref = t::proxy(&name).build()?; - let and = t::optional(t::array(self_ref).build()?).build()?; + let and = t::optionalx(t::array(self_ref))?.build()?; let mut builder = t::struct_(); builder.named(name); @@ -35,7 +35,7 @@ impl TypeGen for QueryWhereExpr { } builder.prop("AND", and); builder.prop("OR", and); - builder.prop("NOT", t::optional(self_ref).build()?); + builder.propx("NOT", t::optional(self_ref))?; builder.build() } diff --git a/typegraph/core/src/runtimes/prisma/type_generation/update_input.rs b/typegraph/core/src/runtimes/prisma/type_generation/update_input.rs index ebdeadfecd..e5b5e542c5 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/update_input.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/update_input.rs @@ -34,17 +34,17 @@ impl TypeGen for UpdateInput { let mutation_type = match typ { Type::Optional(_) => unreachable!(), Type::Boolean(_) | Type::String(_) => { - t::union([type_id, t::struct_().prop("set", type_id).build()?]).build()? + t::unionx![type_id, t::struct_().prop("set", type_id)].build()? } Type::Integer(_) | Type::Float(_) => { let wrapped_type_id = typ.get_id(); - t::union([ + t::unionx![ wrapped_type_id, - t::struct_().prop("set", type_id).build()?, - t::struct_().prop("multiply", wrapped_type_id).build()?, - t::struct_().prop("decrement", wrapped_type_id).build()?, - t::struct_().prop("increment", wrapped_type_id).build()?, - ]) + t::struct_().prop("set", type_id), + t::struct_().prop("multiply", wrapped_type_id), + t::struct_().prop("decrement", wrapped_type_id), + t::struct_().prop("increment", wrapped_type_id), + ] .build()? } Type::Array(inner) => { @@ -58,12 +58,12 @@ impl TypeGen for UpdateInput { // scalar list: only supported in PostgreSQL, CockroachDB and MongoDB // see: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#relational-databases let item_type = inner.data.of.into(); - t::union([ + t::unionx![ type_id, - t::struct_().prop("set", type_id).build()?, - t::struct_().prop("push", item_type).build()?, + t::struct_().prop("set", type_id), + t::struct_().prop("push", item_type), // "unset": mongo only - ]) + ] .build()? } _ => { @@ -73,7 +73,7 @@ impl TypeGen for UpdateInput { } }; - builder.prop(key, t::optional(mutation_type).build()?); + builder.propx(key, t::optional(mutation_type))?; } builder.named(self.name()).build() diff --git a/typegraph/core/src/runtimes/prisma/type_generation/where_.rs b/typegraph/core/src/runtimes/prisma/type_generation/where_.rs index 937b89bf0e..44d63bd229 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/where_.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/where_.rs @@ -38,14 +38,14 @@ impl TypeGen for Where { model_id: model.model_type, relations: false, })?; - builder.prop(key, t::optional(inner).build()?); + builder.propx(key, t::optional(inner))?; } else { let non_optional = type_id.non_optional_concrete_type()?; match non_optional.as_type()? { Type::Optional(_) => unreachable!(), Type::Func(_) => continue, _ => { - builder.prop(key, t::optional(non_optional).build()?); + builder.propx(key, t::optional(non_optional))?; } } } diff --git a/typegraph/core/src/runtimes/prisma/type_generation/with_filters.rs b/typegraph/core/src/runtimes/prisma/type_generation/with_filters.rs index ef09547b9c..67f981ed3b 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/with_filters.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/with_filters.rs @@ -79,7 +79,7 @@ impl TypeGen for WithFilters { } } }; - builder.prop(key, t::optional(generated).build()?); + builder.propx(key, t::optional(generated))?; } builder.named(self.name()).build() @@ -102,7 +102,7 @@ impl TypeGen for CompleteFilter { fn generate(&self, context: &mut TypeGenContext) -> Result { let inner = context.generate(&self.0)?; // TODO and, or ??? - t::optional(t::union([inner, t::struct_().prop("not", inner).build()?]).build()?) + t::optionalx(t::unionx![inner, t::struct_().prop("not", inner)])? .named(self.name()) .build() } @@ -116,11 +116,11 @@ struct BooleanFilter; impl TypeGen for BooleanFilter { fn generate(&self, _context: &mut TypeGenContext) -> Result { - t::union([ + t::unionx![ t::boolean().build()?, - t::struct_().prop("equals", t::boolean().build()?).build()?, - t::struct_().prop("not", t::boolean().build()?).build()?, - ]) + t::struct_().propx("equals", t::boolean())?, + t::struct_().propx("not", t::boolean())?, + ] .named(self.name()) .build() } @@ -156,14 +156,14 @@ impl TypeGen for NumberFilter { let base = context.generate(&NumberFilter::new(self.number_type, false))?; let float_base = context.generate(&NumberFilter::new(NumberType::Float, false))?; let int_base = context.generate(&NumberFilter::new(NumberType::Integer, false))?; - t::union([ + t::unionx![ base, - t::struct_().prop("_count", int_base).build()?, - t::struct_().prop("_sum", base).build()?, - t::struct_().prop("_avg", float_base).build()?, - t::struct_().prop("_min", base).build()?, - t::struct_().prop("_max", base).build()?, - ]) + t::struct_().prop("_count", int_base), + t::struct_().prop("_sum", base), + t::struct_().prop("_avg", float_base), + t::struct_().prop("_min", base), + t::struct_().prop("_max", base), + ] .named(self.name()) .build() } else { @@ -173,20 +173,19 @@ impl TypeGen for NumberFilter { }; let opt_type_id = t::optional(type_id).build()?; let array_type_id = t::array(type_id).build()?; - t::either([ + t::eitherx![ type_id, - t::struct_().prop("equals", type_id).build()?, - t::struct_().prop("not", type_id).build()?, + t::struct_().prop("equals", type_id), + t::struct_().prop("not", type_id), t::struct_() .prop("lt", opt_type_id) .prop("gt", opt_type_id) .prop("lte", opt_type_id) .prop("gte", opt_type_id) - .min(1) - .build()?, - t::struct_().prop("in", array_type_id).build()?, - t::struct_().prop("notIn", array_type_id).build()?, - ]) + .min(1), + t::struct_().prop("in", array_type_id), + t::struct_().prop("notIn", array_type_id), + ] .named(self.name()) .build() } @@ -213,28 +212,23 @@ impl TypeGen for StringFilter { let opt_type_id = t::optional(type_id).build()?; let array_type_id = t::array(type_id).build()?; - t::union([ + t::unionx![ type_id, - t::struct_().prop("equals", type_id).build()?, - t::struct_().prop("not", type_id).build()?, - t::struct_().prop("in", array_type_id).build()?, - t::struct_().prop("notIn", array_type_id).build()?, - t::struct_() - .prop("contains", type_id) - .prop( - "mode", - t::optional(t::string().enum_(vec!["insensitive".to_string()]).build()?) - .build()?, - ) - .build()?, + t::struct_().prop("equals", type_id), + t::struct_().prop("not", type_id), + t::struct_().prop("in", array_type_id), + t::struct_().prop("notIn", array_type_id), + t::struct_().prop("contains", type_id).prop( + "mode", + t::optional(t::string().enum_(vec!["insensitive".to_string()]).build()?).build()?, + ), // TODO optional feature -- previewFeatures = ["fullTextSearch"] - t::struct_().prop("search", type_id).build()?, + t::struct_().prop("search", type_id), t::struct_() .prop("startsWith", opt_type_id) .prop("endsWith", opt_type_id) - .min(1) - .build()?, - ]) + .min(1), + ] .named(self.name()) .build() } @@ -255,22 +249,14 @@ impl TypeGen for ScalarListFilter { // we can use union here instead of either since the structs do not have // overlapping fields. // Union validation is more efficient. - t::union([ - t::struct_().prop("has", self.0).build()?, - t::struct_() - .prop("hasEvery", t::array(self.0).build()?) - .build()?, - t::struct_() - .prop("hasSome", t::array(self.0).build()?) - .build()?, - t::struct_() - .prop("isEmpty", t::boolean().build()?) - .build()?, + t::unionx![ + t::struct_().prop("has", self.0), + t::struct_().propx("hasEvery", t::array(self.0))?, + t::struct_().propx("hasSome", t::array(self.0))?, + t::struct_().propx("isEmpty", t::boolean())?, // TODO "isSet": mongo only - t::struct_() - .prop("equals", t::array(self.0).build()?) - .build()?, - ]) + t::struct_().propx("equals", t::array(self.0))?, + ] .named(self.name()) .build() } diff --git a/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs b/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs index e54e3c56d4..9a04806d8c 100644 --- a/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs +++ b/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs @@ -42,7 +42,7 @@ impl TypeGen for WithNestedCount { model_id: relation_model.model_type, skip: [self.skip.as_slice(), &[rel.name.clone()]].concat(), })?; - builder.prop(key, t::optional(inner).build()?); + builder.propx(key, t::optional(inner))?; countable.push(key.to_string()); } Cardinality::Many => { @@ -50,7 +50,7 @@ impl TypeGen for WithNestedCount { model_id: relation_model.model_type, skip: [self.skip.as_slice(), &[rel.name.clone()]].concat(), })?; - builder.prop(key, t::array(inner).build()?); + builder.propx(key, t::array(inner))?; countable.push(key.to_string()); } Cardinality::One => { @@ -68,7 +68,7 @@ impl TypeGen for WithNestedCount { for prop in countable.into_iter() { count.prop(prop, context.generate(&Count)?); } - builder.prop("_count", count.build()?); + builder.propx("_count", count)?; } builder.named(self.name()).build() diff --git a/typegraph/core/src/t.rs b/typegraph/core/src/t.rs index bb245aba45..8c8fcd38e6 100644 --- a/typegraph/core/src/t.rs +++ b/typegraph/core/src/t.rs @@ -9,13 +9,28 @@ use crate::wit::core::{ }; pub trait TypeBuilder { - fn build(&mut self) -> Result; + fn build(&self) -> Result; - fn optional(&mut self) -> Result { + fn optional(&self) -> Result { Ok(optional(self.build()?)) } } +impl TypeBuilder for &mut T +where + T: TypeBuilder, +{ + fn build(&self) -> Result { + (**self).build() + } +} + +impl TypeBuilder for TypeId { + fn build(&self) -> Result { + Ok(*self) + } +} + pub trait ConcreteTypeBuilder: TypeBuilder { fn base_mut(&mut self) -> &mut TypeBase; @@ -217,6 +232,10 @@ pub fn optional(ty: TypeId) -> OptionalBuilder { } } +pub fn optionalx(item_builder: impl TypeBuilder) -> Result { + Ok(optional(item_builder.build()?)) +} + #[derive(Default)] pub struct ArrayBuilder { base: TypeBase, @@ -244,7 +263,7 @@ pub fn array(ty: TypeId) -> ArrayBuilder { } } -pub fn arrayx(mut item_builder: impl TypeBuilder) -> Result { +pub fn arrayx(item_builder: impl TypeBuilder) -> Result { Ok(array(item_builder.build()?)) } @@ -272,6 +291,17 @@ pub fn union(variants: impl IntoIterator) -> UnionBuilder { } } +macro_rules! unionx { + [ $($ty:expr),* ] => { + $crate::t::union(vec![$($ty.build()?),*]) + }; + + [ $($ty:expr),*, ] => { + crate::t::unionx![$($ty),*] + }; +} +pub(crate) use unionx; + #[derive(Default)] pub struct EitherBuilder { base: TypeBase, @@ -296,6 +326,17 @@ pub fn either(variants: impl IntoIterator) -> EitherBuilder { } } +macro_rules! eitherx { + [ $($ty:expr),* ] => { + $crate::t::either(vec![$($ty.build()?),*]) + }; + + [ $($ty:expr),*, ] => { + crate::t::eitherx![$($ty),*] + }; +} +pub(crate) use eitherx; + #[derive(Default)] pub struct StructBuilder { base: TypeBase, @@ -348,7 +389,7 @@ impl StructBuilder { pub fn propx( &mut self, name: impl Into, - mut builder: impl TypeBuilder, + builder: impl TypeBuilder, ) -> Result<&mut Self> { self.data.props.push((name.into(), builder.build()?.into())); Ok(self) @@ -439,9 +480,9 @@ pub fn proxy(name: impl Into) -> ProxyBuilder { macro_rules! impl_type_builder { ( $ty:ty, $build:ident ) => { impl TypeBuilder for $ty { - fn build(&mut self) -> Result { - let builder = std::mem::take(self); - Ok($crate::Lib::$build(builder.data, builder.base)?.into()) + fn build(&self) -> Result { + let builder = self.clone(); + Ok($crate::Lib::$build(builder.data.clone(), builder.base.clone())?.into()) } } @@ -454,17 +495,17 @@ macro_rules! impl_type_builder { ( $ty:ty, $build:ident, true ) => { impl TypeBuilder for $ty { - fn build(&mut self) -> Result { - let builder = std::mem::take(self); - Ok($crate::Lib::$build(builder.data)?.into()) + fn build(&self) -> Result { + let builder = self.clone(); + Ok($crate::Lib::$build(builder.data.clone())?.into()) } } }; } impl TypeBuilder for BooleanBuilder { - fn build(&mut self) -> Result { - let builder = std::mem::take(self); - Ok(crate::Lib::booleanb(builder.base)?.into()) + fn build(&self) -> Result { + let builder = self.clone(); + Ok(crate::Lib::booleanb(builder.base.clone())?.into()) } }