Open t1ltxz-gxd opened 7 months ago
The library is trying to simply be representations of the API, which is still unstable. After the changes, does the example work?
I changed it a little bit and now I have Meitantei Conan as the answer. Below is the code that is currently working
use chrono::{DateTime, Utc};
use shikimori::{client::ClientBuilder,
cynic,
cynic::{Id, QueryFragment, QueryVariables, QueryBuilder},
graphql::{
anime::AnimeKind,
types::EntityOrder,
scalars::{AnimeStatusString},
schema
}
};
#[derive(QueryVariables, Debug)]
pub struct AnimesQueryVariables {
pub page: i32,
pub status: AnimeStatusString,
pub order: EntityOrder,
}
#[derive(QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "AnimesQueryVariables", schema_path = "../schema.graphql")]
pub struct AnimesQuery {
#[arguments(censored: false, page: $page, status: $status, order: $order)]
pub animes: Vec<Anime>,
}
#[derive(QueryFragment, Debug)]
#[cynic(graphql_type = "Anime", variables = "AnimesQueryVariables", schema_path = "../schema.graphql")]
pub struct Anime {
pub id: Id,
pub franchise: Option<String>,
pub episodes: i32,
pub kind: Option<AnimeKind>,
pub next_episode_at: Option<DateTime<Utc>>,
pub url: String,
}
#[tokio::main]
async fn main() {
let client = ClientBuilder::new().build();
let response = client
.query(AnimesQuery::build(AnimesQueryVariables {
page: 1,
status: AnimeStatusString::new("ongoing"),
order: EntityOrder::Popularity,
}))
.await;
dbg!(&response);
}
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
Running `target/debug/shikimori`
[shikimori/src/main.rs:51:5] &response = Ok(
GraphQlResponse {
data: Some(
AnimesQuery {
animes: [
Anime {
id: Id(
"21",
),
franchise: Some(
"one_piece",
),
episodes: 0,
kind: Some(
Tv,
),
next_episode_at: Some(
2024-05-05T00:30:00Z,
),
url: "https://shikimori.one/animes/21-one-piece",
},
Anime {
id: Id(
"235",
),
franchise: Some(
"detective_conan",
),
episodes: 0,
kind: Some(
Tv,
),
next_episode_at: Some(
2024-05-04T09:00:00Z,
),
url: "https://shikimori.one/animes/z235-meitantei-conan",
},
],
},
),
errors: None,
},
)
Process finished with exit code 0
I had to download schema.graphql
from shikimori to get the code to work
I've been thinking about how to make this point better, but haven't come to a conclusion yet. Maybe I should create a feature that will export the following code:
#[cfg(feature = "codegen")]
pub fn register_schema() {
cynic_codegen::register_schema("shikimori")
.from_sdl(include_str!("./schema.graphql"))
.unwrap()
.as_default()
.unwrap();
}
in my opinion, the build should affect derive so that library users do not need to download the schema for their code to work
I noticed that r.n. there is a problem with the error Unresolved import: shikimori::graphql::schema
[E0432].
Build should generate an exportable module schema
for this to solve the problem 🐣
Now you can specify in build-dependencies:
[build-dependencies]
shikimori = { version = "0.4.0", features = ["register-graphql-schema"] }
And then in the build.rs
fn main() {
shikimori::graphql::register_schema();
}
smth wrong in the build.rs
:
error[E0433]: failed to resolve: use of undeclared crate or module `shikimori`
--> build.rs:2:5
|
2 | shikimori::graphql::register_schema();
| ^^^^^^^^^ use of undeclared crate or module `shikimori`
*missclick
Was a dependency added with the register-graphql-schema
feature enabled? It is better to duplicate 2 times for build and common dependencies.
# Cargo.toml
[dependencies]
shikimori = { version = "0.4.0" }
[build-dependencies]
shikimori = { version = "0.4.0", features = ["register-graphql-schema"] }
Oooops! My bad, I added the feature to dependencies, not to build dependencies, but now I have a new error:
error[E0277]: the trait bound `i32: CoercesTo<std::option::Option<shikimori::graphql::schema::PositiveInt>>` is not satisfied
--> src/service/external/api/shikimori/query.rs:27:10
|
27 | #[derive(QueryFragment, Debug)]
| ^^^^^^^^^^^^^ the trait `CoercesTo<std::option::Option<shikimori::graphql::schema::PositiveInt>>` is not implemented for `i32`
|
= help: the following other types implement trait `CoercesTo<T>`:
<i32 as CoercesTo<Vec<Vec<i32>>>>
<i32 as CoercesTo<Vec<i32>>>
<i32 as CoercesTo<i32>>
<i32 as CoercesTo<std::option::Option<Vec<i32>>>>
<i32 as CoercesTo<std::option::Option<Vec<std::option::Option<i32>>>>>
<i32 as CoercesTo<std::option::Option<i32>>>
<i32 as CoercesTo<std::option::Option<std::option::Option<i32>>>>
note: required by a bound in `queries::builders::InputBuilder::<'a, SchemaType, VariablesFields>::variable`
--> /home/t1ltxz-gxd/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cynic-3.7.0/src/queries/builders.rs:274:15
|
272 | pub fn variable<Type>(self, def: VariableDefinition<VariablesFields, Type>)
| -------- required by a bound in this associated function
273 | where
274 | Type: CoercesTo<SchemaType>,
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `InputBuilder::<'a, SchemaType, VariablesFields>::variable`
= note: this error originates in the derive macro `QueryFragment` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0277`.
My query with problem:
#[derive(QueryFragment, Debug)] // 27 line
#[cynic(graphql_type = "Query", variables = "MyQueryVariables" )] // 28 line
pub struct MyQuery { // 29 line
#[arguments(limit: $limit, page: $page, order: $order)] // 30 line
pub animes: Vec<Anime>, // 31 line
#[arguments(limit: $limit, page: $page, order: $order)] //32 line
pub mangas: Vec<Manga>, // 33 line
#[arguments(limit: $limit, page: $page)] // 34 line
pub characters: Vec<Character>, // 35 line
} // 36 line
...
#[derive(QueryVariables, Debug)]
pub struct MyQueryVariables {
pub page: i32,
pub limit: i32,
pub order: EntityOrder,
}
Shikimori now requires Scalar PositiveInt
for page
and limit
# A positive integer (>= 1)
scalar PositiveInt
type Query {
animes(
page: PositiveInt = 1
# Maximum 50
limit: PositiveInt = 2
# ...
): [Anime!]!
}
You need to modify the query as follows
+ shikimori::graphql::scalars::PositiveInt;
#[derive(QueryFragment, Debug)] // 27 line
#[cynic(graphql_type = "Query", variables = "MyQueryVariables" )] // 28 line
pub struct MyQuery { // 29 line
#[arguments(limit: $limit, page: $page, order: $order)] // 30 line
pub animes: Vec<Anime>, // 31 line
#[arguments(limit: $limit, page: $page, order: $order)] //32 line
pub mangas: Vec<Manga>, // 33 line
#[arguments(limit: $limit, page: $page)] // 34 line
pub characters: Vec<Character>, // 35 line
} // 36 line
...
#[derive(QueryVariables, Debug)]
pub struct MyQueryVariables {
- pub page: i32,
+ pub page: PositiveInt,
- pub limit: i32,
+ pub limit: PositiveInt,
pub order: EntityOrder,
}
MyQueryVariables {
page: PositiveInt::new(1),
limit: PositiveInt::new(10),
// ...
}
P.S. Isn't that too big of a query in GraphQL? It will put a lot of load on the database.
Ok, then schema can no longer be used for query variable:
error[E0433]: failed to resolve: use of undeclared crate or module `schema`
--> src/service/external/api/shikimori/query.rs:13:10
|
13 | #[derive(QueryVariables, Debug)]
| ^^^^^^^^^^^^^^ use of undeclared crate or module `schema`
|
= note: this error originates in the derive macro `QueryVariables` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider importing this module
P.S. Isn't that too big of a query in GraphQL? It will put a lot of load on the database.
Lol, it turns out if you make a large request, the fields description
, duration
, english
, episodes
, episodes_aired
, franchise
, kind
, next_episode_at
, rating
, score, season
, status
, synonyms
in anime and description
, english
, franchise
, kind
, score
in manga will be NULL
Btw,i split the query into several parts so as not to overload the database 😎
@t1ltxz-gxd Does the example in the README work? Well and I need more context on the query.
Build output:
My code taken from the example use case:
Here I only changed use
scalars::{StatusString}
toscalars::{AnimeStatusString}
, cause the code was refactored but you forgot to update the example =)