Open iterable-company opened 1 year ago
JuniperはWebサーバは含まない。
代わりに、Hyper, Iron, Rocket, Warp をフレームワークとして使える。
specificationに完全にサポートしている。
デフォルトではnon-nullで構築する。
Vec<Episode>
→ [Episode!]!
[Episode]
→ Option<Vec<Option<Episode>>>
以下のクレートの型は自動で使うことができる。
[dependencies]
juniper = "0.10"
enum, struct にカスタムのderive attribute をつけるだけで良い。
以下のようなタイプを自然な形でGraphQLにマッピングする。
最も重要なものは graphql_object!
マクロで resolver とともにオブジェクトを宣言する。
#[derive(GraphQLObject)]
/// Information about a person
struct Person {
/// The person's full name, including both first and last names
name: String,
/// The person's age in years, rounded down
age: i32,
}
コメントはgraphQLのdescriptionになる。
#[derive(GraphQLObject)]
#[graphql(description="Information about a person")]
struct Person {
#[graphql(description="The person's full name, including both first and last names")]
name: String,
#[graphql(description="The person's age in years, rounded down")]
age: i32,
}
のように、description
をattributeにつけても良い。
attributeの方が優先順位が高いため、Rustのドキュメントしてはdoc commentを使用し、attributeの方をgraphQLのドキュメントdescriptionとして利用できる。
以下の条件に合致する場合にのみ、カスタムのderive attributeを使える
例
extern crate juniper;
#[macro_use] extern crate juniper_codegen;
#[derive(GraphQLObject)]
struct Person {
name: String,
age: i32,
}
#[derive(GraphQLObject)]
struct House {
address: Option<String>, // Converted into String (nullable)
inhabitants: Vec<Person>, // Converted into [Person!]!
}
PersonはvalidなGraphQLタイプなので、 Vec
rustはsnake case, GraphQLはcamelCaseなので以下のようになる。
#[derive(GraphQLObject)]
struct Person {
first_name: String, // Would be exposed as firstName in the GraphQL schema
last_name: String, // Exposed as lastName
}
これを変えたい個別のフィールドに対して以下のように graphql attributeを使う
#[derive(GraphQLObject)]
struct Person {
name: String,
age: i32,
#[graphql(name="websiteURL")]
website_url: Option<String>, // Now exposed as websiteURL in the schema
}
deprecate の理由を含めて、 graphql attribute に書くことができる。
#[derive(GraphQLObject)]
struct Person {
name: String,
age: i32,
#[graphql(deprecation="Please use the name field instead")]
first_name: String,
}
graphql attribute の name, description, deprecation は共存できる。
デフォルトでは全てのフィールドがgraphqlのフィールドとなるが、graphQLに含ませないようにできる。
#[derive(GraphQLObject)]
struct Person {
name: String,
age: i32,
#[graphql(skip)]
password_hash: String, // This cannot be queried or modified from GraphQL
}
直接GraphQLにマッピングできないstructの場合、例えばフィールドを計算したり、循環構造を持っているような場合、より強力なツールである graphql_object!
を使うことができる。このマクロを使うと Rust の impl ブロックと同じようなやり方で graphQL objectを定義することができるようになる。
#[macro_use] extern crate juniper;
struct Person {
name: String,
age: i32,
}
graphql_object!(Person: () |&self| {
field name() -> &str {
self.name.as_str()
}
field age() -> i32 {
self.age
}
});
より冗長なもので、以下のようにフィールドがパラメータを受け取るようにもできる。
#[derive(GraphQLObject)]
struct Person {
name: String,
age: i32,
}
struct House {
inhabitants: Vec<Person>,
}
graphql_object!(House: () |&self| {
// Creates the field inhabitantWithName(name), returning a nullable person
field inhabitant_with_name(name: String) -> Option<&Person> {
self.inhabitants.iter().find(|p| p.name == name)
}
});
derive attribute のように、フィールド名はsnake case から camelCase へと変換される。
もし、このconventionをoverrideしたければ、以下のようにできる。
#[macro_use] extern crate juniper;
struct Person {
name: String,
website_url: String,
}
graphql_object!(Person: () as "PersonObject" |&self| {
field name() -> &str {
self.name.as_str()
}
field websiteURL() -> &str {
self.website_url.as_str()
}
});
GraphQLのフィールドは RustのメソッドのSyntaxよりもよりfeatureを公開できる。
default value
graphql_input_object!(
struct SampleObject {
foo = 123: i64 as "A sample field, defaults to 123 if omitted"
}
);
https://graphql-rust.github.io/
を読んでいきつつ、必要であればメモしていくためのチケット。