diff --git a/docs/en/src/context.md b/docs/en/src/context.md index c4030388..21c35b7c 100644 --- a/docs/en/src/context.md +++ b/docs/en/src/context.md @@ -1 +1,21 @@ # Context + +The main goal of `Context` is to acquire global data attached to Schema. **Note that if the return value of your Resulve boored data in `Context`, you need to explictly state the lifetime of the argument.** + +The following example shows how to borrow data in `Context`. + +```rust +use async_graphql::*; + +struct Query; + +#[Object] +impl Query { + async fn borrow_from_context_data<'ctx'>( + &self, + ctx: &'ctx Context<'_> + ) -> &'ctx String { + ctx.data:: + } +} +``` \ No newline at end of file diff --git a/docs/en/src/define_complex_object.md b/docs/en/src/define_complex_object.md index c0ddad0d..ff6158e6 100644 --- a/docs/en/src/define_complex_object.md +++ b/docs/en/src/define_complex_object.md @@ -1 +1,34 @@ # Object + +Different from `SimpleObject`, `Object` must have Resolve defined for each field in `impl`. + +**A Resolve function has to be asynchronous. The first argument has to be `&self`, second being optional `Context` and followed by field arguments.** + +Resolve is used to get the value of the field. You can query a database and return the result. **The return type of the function is the type of the field.** You can also return a `async_graphql::FieldResult` so to return an error if it occrs and error message will be send to query result. + + +When querying a database, you may need a global data base connection pool, you can use `Schema::data` to attach a global data when creating Schema, the following `value_from_db` function showed how to retrive a database connection from `Context`. + +```rust +use async_graphql::*; + +struct MyObject { + value: i32, +} + +#[Object] +impl MyObject { + async fn value(&self) -> String { + self.value.to_string() + } + + async fn value_from_db( + &self, + ctx: &Context<'_'>, + #[arg(desc = "Id of object")] id: i64 + ) -> FieldResult { + let conn = ctx.data::().take(); + Ok(conn.query_something(id)?.name) + } +} +``` \ No newline at end of file diff --git a/docs/en/src/define_enum.md b/docs/en/src/define_enum.md index be77ea9c..b03e6526 100644 --- a/docs/en/src/define_enum.md +++ b/docs/en/src/define_enum.md @@ -1 +1,22 @@ # Enum + +It's easy to define an `Enum`, here we have an example: + +**Async-graphql can automatically change the name of each item to GraphQL's convsion (all capitals and underscores), you can also use `name` to rename.** + +```rust +use async_graphql::*; + +#[Enum(desc = "One of the films in the Star Wars Trilogy")] +pub enum Episode { + #[item(desc = "Released in 1977.")] + NewHope, + + #[item(desc = "Released in 1980.")] + Empire, + + // rename to `AAA` + #[item(name="AAA", desc = "Released in 1983.")] + Jedi, +} +``` \ No newline at end of file diff --git a/docs/en/src/define_input_object.md b/docs/en/src/define_input_object.md index 7511b9dc..0589d4ea 100644 --- a/docs/en/src/define_input_object.md +++ b/docs/en/src/define_input_object.md @@ -1 +1,31 @@ # InputObject + + +You can define an `Object` as argument, GraphQL calls it `InputObject`. +The definition of `InputObject` is similar to [SimpleObject](define_simple_object.md). +However, `InputObject` can only be used for output and `SimpleObject` can only be used as input. + +`InputObject` don't need a `#[field]` for each field, every field is `InputValue`. +But you can add optional `#[field]` to add description or rename the field. + +```rust +use async_graphql::*; + +#[InputObject] +struct Coordinate { + latitude: f64, + + #[field(desc = "...")] + longitude: f64 +} + +struct Mutation; + +#[Object] +impl Mutation { + async fn users_at_location(&self, coordinate: Coordinate, radius: f64) -> Vec { + // Writes coordination to database. + // ... + } +} +``` \ No newline at end of file diff --git a/docs/en/src/define_interface.md b/docs/en/src/define_interface.md index fa54d335..95d428ce 100644 --- a/docs/en/src/define_interface.md +++ b/docs/en/src/define_interface.md @@ -1 +1,48 @@ # Interface + +`Interface` is used to abstract `Object`s with common fields. +`Async-graphql` implemented it as a wrapper. +The wrapper will forward Resolve to the `Object` that implemented this `Interface`. +Therefore, the `Object`'s fields' type, arguments must match with the `Interface`'s. + +`Async-graphql` implemented auto conversion from `Object` to `Interface`, you only need to call `Into::into`. + +```rust +use async_graphql::*; + +struct Circle { + radius: f32, +} + +#[Object] +impl Circle { + async fn area(&self) -> f32 { + std::f32::consts::PI * self.radius * self.radius + } + + async fn scale(&self, s: f32) -> Shape { + Circle { radius: self.radius * s }.into() + } +} + +struct Square { + width: f32, +} + +#[Object] +impl Square { + async fn area(&self) -> f32 { + self.width * self.width + } + + async fn scale(&self, s: f32) -> Shape { + Square { width: self.width * s }.into() + } +} + +#[Interface( + field(name = "area", type = "f32"), + field(name = "scale", type = "Shape", arg(name = "s", type = "f32")) +)] +struct Shape(Circle, Square); +``` \ No newline at end of file diff --git a/docs/en/src/define_simple_object.md b/docs/en/src/define_simple_object.md index f35daa2b..d1640a62 100644 --- a/docs/en/src/define_simple_object.md +++ b/docs/en/src/define_simple_object.md @@ -1 +1,18 @@ # SimpleObject + +`SimpleObject` directly map all field of a struct to GraphQL object, you cannot define a Resolve function on it. + +The example below defined an object `MyObject`, including field `a` and `b`. `c` will be not mapped to GraphQL as it is labelled as `#[field(skip)]` + +```rust +use async_graphql::*; + +#[SimpleObject] +struct MyObject { + a: i32, + b: i32, + + #[field(skip)] + c: i32, +} +``` diff --git a/docs/en/src/define_union.md b/docs/en/src/define_union.md index e530b453..136ff959 100644 --- a/docs/en/src/define_union.md +++ b/docs/en/src/define_union.md @@ -1 +1,44 @@ # Union + +The definition of `Union` is similar to `Interface`'s, **but no field allowed.**. +The implemention is quite similar for `Async-graphql`. +From `Async-graphql`'s perspective, `Union` is a subset of `Interface`. + +The following example modified the definition of `Interface` a little bit and removed fields. + +```rust +use async_graphql::*; + +struct Circle { + radius: f32, +} + +#[Object] +impl Circle { + async fn area(&self) -> f32 { + std::f32::consts::PI * self.radius * self.radius + } + + async fn scale(&self, s: f32) -> Shape { + Circle { radius: self.radius * s }.into() + } +} + +struct Square { + width: f32, +} + +#[Object] +impl Square { + async fn area(&self) -> f32 { + self.width * self.width + } + + async fn scale(&self, s: f32) -> Shape { + Square { width: self.width * s }.into() + } +} + +#[Union] +struct Shape(Circle, Square); +``` \ No newline at end of file diff --git a/docs/en/src/error_handling.md b/docs/en/src/error_handling.md index face61c6..8cbed094 100644 --- a/docs/en/src/error_handling.md +++ b/docs/en/src/error_handling.md @@ -1 +1,28 @@ # Error handling + +Resolve can return a `FieldResult`, following is the definition: + +```rust +type FieldResult = std::result::Result; +``` + + +Any `Error` can be converted to `FieldError` and you can extend error message. + +Following example shows how to parse an input string to integer. When parsing failed, it would return error and attach error message. + +```rust +use async_graphql::*; + +struct Query; + +#[Object] +impl Query { + #[field] + async fn parse_with_extensions(&self, input: String) -> FieldResult { + Ok("234a" + .parse() + .map_err(|err| err.extend_with(|_| json!({"code": 400})))?) + } +} +``` \ No newline at end of file diff --git a/docs/en/src/typesystem.md b/docs/en/src/typesystem.md index 6b07ea95..21dbbf95 100644 --- a/docs/en/src/typesystem.md +++ b/docs/en/src/typesystem.md @@ -1 +1,3 @@ # Type System + +`Async-graphql` implemented conversion from GraphQL Object to Rust struct, and it's easy to use. \ No newline at end of file