Merge branch 'async-await' into remove-async-closure-feature

# Conflicts:
#	examples/warp_async/src/main.rs
#	integration_tests/async_await/src/main.rs
#	juniper/src/lib.rs
#	juniper_benchmarks/src/lib.rs
#	juniper_rocket/src/lib.rs
#	juniper_warp/src/lib.rs
This commit is contained in:
tyranron 2019-10-10 13:20:00 +02:00
commit 635bf1ff34
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
26 changed files with 344 additions and 45 deletions

View file

@ -2,9 +2,15 @@
- No changes yet
# [[0.14.0] 2019-09-29](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.14.0)
- Require `url` 2.x if `url` feature is enabled.
- Improve lookahead visitability.
- Add ability to parse 'subscription'.
# [[0.13.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.13.1)
- Fix a regression when using lookaheads with fragments containing nested types [#404](https://github.com/graphql-rust/juniper/pull/404)
- Fix a regression when using lookaheads with fragments containing nested types [#404](https://github.com/graphql-rust/juniper/pull/404)
- Allow `mut` arguments for resolver functions in `#[object]` macros [#402](https://github.com/graphql-rust/juniper/pull/402)
@ -15,7 +21,7 @@
See [#345](https://github.com/graphql-rust/juniper/pull/345).
The newtype pattern can now be used with the `GraphQLScalarValue` custom derive
to easily implement custom scalar values that just wrap another scalar,
to easily implement custom scalar values that just wrap another scalar,
similar to serdes `#[serde(transparent)]` functionality.
Example:
@ -34,7 +40,7 @@ struct UserId(i32);
### object macro
The `graphql_object!` macro is deprecated and will be removed in the future.
The `graphql_object!` macro is deprecated and will be removed in the future.
It is replaced by the new [object](https://docs.rs/juniper/latest/juniper/macro.object.html) procedural macro.
[#333](https://github.com/graphql-rust/juniper/pull/333)
@ -53,7 +59,7 @@ This should not have any impact on your code, since juniper already was 2018 com
- The `GraphQLType` impl for () was removed to improve compile time safefty. [#355](https://github.com/graphql-rust/juniper/pull/355)
- The `ScalarValue` custom derive has been renamed to `GraphQLScalarValue`.
- Added built-in support for the canonical schema introspection query via
`juniper::introspect()`.
`juniper::introspect()`.
[#307](https://github.com/graphql-rust/juniper/issues/307)
- Fix introspection query validity
The DirectiveLocation::InlineFragment had an invalid literal value,

View file

@ -1,6 +1,6 @@
[package]
name = "juniper"
version = "0.13.1"
version = "0.14.0"
authors = [
"Magnus Hallin <mhallin@fastmail.com>",
"Christoph Herzog <chris@theduke.at>",
@ -33,7 +33,7 @@ default = [
]
[dependencies]
juniper_codegen = { version = "0.13.2", path = "../juniper_codegen" }
juniper_codegen = { version = "0.14.0", path = "../juniper_codegen" }
fnv = "1.0.3"
indexmap = { version = "1.0.0", features = ["serde-1"] }
@ -42,7 +42,7 @@ serde_derive = { version = "1.0.2" }
chrono = { version = "0.4.0", optional = true }
serde_json = { version="1.0.2", optional = true }
url = { version = "1.5.1", optional = true }
url = { version = "2", optional = true }
uuid = { version = "0.7", optional = true }
futures-preview = { version = "=0.3.0-alpha.19", optional = true }

View file

@ -116,6 +116,7 @@ pub struct Directive<'a, S> {
pub enum OperationType {
Query,
Mutation,
Subscription,
}
#[derive(Clone, PartialEq, Debug)]

View file

@ -88,6 +88,11 @@ where
}
}
/// The argument's name
pub fn name(&'a self) -> &str {
&self.name
}
/// The value of the argument
pub fn value(&'a self) -> &LookAheadValue<'a, S> {
&self.value
@ -347,6 +352,12 @@ pub trait LookAheadMethods<S> {
self.select_child(name).is_some()
}
/// Does the current node have any arguments?
fn has_arguments(&self) -> bool;
/// Does the current node have any children?
fn has_children(&self) -> bool;
/// Get the top level arguments for the current selection
fn arguments(&self) -> &[LookAheadArgument<S>];
@ -354,6 +365,9 @@ pub trait LookAheadMethods<S> {
fn argument(&self, name: &str) -> Option<&LookAheadArgument<S>> {
self.arguments().iter().find(|a| a.name == name)
}
/// Get the top level children for the current selection
fn child_names(&self) -> Vec<&str>;
}
impl<'a, S> LookAheadMethods<S> for ConcreteLookAheadSelection<'a, S> {
@ -368,6 +382,21 @@ impl<'a, S> LookAheadMethods<S> for ConcreteLookAheadSelection<'a, S> {
fn arguments(&self) -> &[LookAheadArgument<S>] {
&self.arguments
}
fn child_names(&self) -> Vec<&str> {
self.children
.iter()
.map(|c| c.alias.unwrap_or(c.name))
.collect()
}
fn has_arguments(&self) -> bool {
!self.arguments.is_empty()
}
fn has_children(&self) -> bool {
!self.children.is_empty()
}
}
impl<'a, S> LookAheadMethods<S> for LookAheadSelection<'a, S> {
@ -385,6 +414,21 @@ impl<'a, S> LookAheadMethods<S> for LookAheadSelection<'a, S> {
fn arguments(&self) -> &[LookAheadArgument<S>] {
&self.arguments
}
fn child_names(&self) -> Vec<&str> {
self.children
.iter()
.map(|c| c.inner.alias.unwrap_or(c.inner.name))
.collect()
}
fn has_arguments(&self) -> bool {
!self.arguments.is_empty()
}
fn has_children(&self) -> bool {
!self.children.is_empty()
}
}
#[cfg(test)]
@ -1399,4 +1443,59 @@ fragment heroFriendNames on Hero {
panic!("No Operation found");
}
}
#[test]
fn check_visitability() {
let docs = parse_document_source::<DefaultScalarValue>(
"
query Hero {
hero(episode: EMPIRE) {
name
friends {
name
}
}
}
",
)
.unwrap();
let fragments = extract_fragments(&docs);
if let crate::ast::Definition::Operation(ref op) = docs[0] {
let vars = Variables::default();
let look_ahead = LookAheadSelection::build_from_selection(
&op.item.selection_set[0],
&vars,
&fragments,
)
.unwrap();
assert_eq!(look_ahead.field_name(), "hero");
assert!(look_ahead.has_arguments());
let args = look_ahead.arguments();
assert_eq!(args[0].name(), "episode");
assert_eq!(args[0].value(), &LookAheadValue::Enum("EMPIRE"));
assert!(look_ahead.has_children());
assert_eq!(look_ahead.child_names(), vec!["name", "friends"]);
let child0 = look_ahead.select_child("name").unwrap();
assert_eq!(child0.field_name(), "name");
assert!(!child0.has_arguments());
assert!(!child0.has_children());
let child1 = look_ahead.select_child("friends").unwrap();
assert_eq!(child1.field_name(), "friends");
assert!(!child1.has_arguments());
assert!(child1.has_children());
assert_eq!(child1.child_names(), vec!["name"]);
let child2 = child1.select_child("name").unwrap();
assert!(!child2.has_arguments());
assert!(!child2.has_children());
} else {
panic!("No Operation found");
}
}
}

View file

@ -713,6 +713,121 @@ where
None => return Err(GraphQLError::UnknownOperationName),
};
if op.item.operation_type == OperationType::Subscription {
return Err(GraphQLError::IsSubscription);
}
let default_variable_values = op.item.variable_definitions.map(|defs| {
defs.item
.items
.iter()
.filter_map(|&(ref name, ref def)| {
def.default_value
.as_ref()
.map(|i| (name.item.to_owned(), i.item.clone()))
})
.collect::<HashMap<String, InputValue<S>>>()
});
let errors = RwLock::new(Vec::new());
let value;
{
let mut all_vars;
let mut final_vars = variables;
if let Some(defaults) = default_variable_values {
all_vars = variables.clone();
for (name, value) in defaults {
all_vars.entry(name).or_insert(value);
}
final_vars = &all_vars;
}
let root_type = match op.item.operation_type {
OperationType::Query => root_node.schema.query_type(),
OperationType::Mutation => root_node
.schema
.mutation_type()
.expect("No mutation type found"),
OperationType::Subscription => unreachable!(),
};
let executor = Executor {
fragments: &fragments
.iter()
.map(|f| (f.item.name.item, &f.item))
.collect(),
variables: final_vars,
current_selection_set: Some(&op.item.selection_set[..]),
parent_selection_set: None,
current_type: root_type,
schema: &root_node.schema,
context,
errors: &errors,
field_path: FieldPath::Root(op.start),
};
value = match op.item.operation_type {
OperationType::Query => executor.resolve_into_value(&root_node.query_info, &root_node),
OperationType::Mutation => {
executor.resolve_into_value(&root_node.mutation_info, &root_node.mutation_type)
}
OperationType::Subscription => unreachable!(),
};
}
let mut errors = errors.into_inner().unwrap();
errors.sort();
Ok((value, errors))
}
#[cfg(feature = "async")]
pub async fn execute_validated_query_async<'a, QueryT, MutationT, CtxT, S>(
document: Document<'a, S>,
operation_name: Option<&str>,
root_node: &RootNode<'a, QueryT, MutationT, S>,
variables: &Variables<S>,
context: &CtxT,
) -> Result<(Value<S>, Vec<ExecutionError<S>>), GraphQLError<'a>>
where
S: ScalarValue + Send + Sync,
QueryT: crate::GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
QueryT::TypeInfo: Send + Sync,
MutationT: crate::GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
MutationT::TypeInfo: Send + Sync,
CtxT: Send + Sync,
for<'b> &'b S: ScalarRefValue<'b>,
{
let mut fragments = vec![];
let mut operation = None;
for def in document {
match def {
Definition::Operation(op) => {
if operation_name.is_none() && operation.is_some() {
return Err(GraphQLError::MultipleOperationsProvided);
}
let move_op = operation_name.is_none()
|| op.item.name.as_ref().map(|s| s.item) == operation_name;
if move_op {
operation = Some(op);
}
}
Definition::Fragment(f) => fragments.push(f),
};
}
let op = match operation {
Some(op) => op,
None => return Err(GraphQLError::UnknownOperationName),
};
let default_variable_values = op.item.variable_definitions.map(|defs| {
defs.item
.items
@ -766,9 +881,15 @@ where
};
value = match op.item.operation_type {
OperationType::Query => executor.resolve_into_value(&root_node.query_info, &root_node),
OperationType::Query => {
executor
.resolve_into_value_async(&root_node.query_info, &root_node)
.await
}
OperationType::Mutation => {
executor.resolve_into_value(&root_node.mutation_info, &root_node.mutation_type)
executor
.resolve_into_value_async(&root_node.mutation_info, &root_node.mutation_type)
.await
}
};
}

View file

@ -70,6 +70,10 @@ impl<'a> ser::Serialize for GraphQLError<'a> {
message: "Unknown operation",
}]
.serialize(serializer),
GraphQLError::IsSubscription => [SerializeHelper {
message: "Expected query, got subscription",
}]
.serialize(serializer),
}
}
}

View file

@ -88,8 +88,7 @@ Juniper has not reached 1.0 yet, thus some API instability should be expected.
[chrono]: https://crates.io/crates/chrono
*/
#![doc(html_root_url = "https://docs.rs/juniper/0.13.1")]
#![doc(html_root_url = "https://docs.rs/juniper/0.14.0")]
#![warn(missing_docs)]
#[doc(hidden)]
@ -191,6 +190,7 @@ pub enum GraphQLError<'a> {
NoOperationProvided,
MultipleOperationsProvided,
UnknownOperationName,
IsSubscription,
}
/// Execute a query in a provided schema

View file

@ -56,9 +56,12 @@ where
S: ScalarValue,
{
match parser.peek().item {
Token::CurlyOpen | Token::Name("query") | Token::Name("mutation") => Ok(
Definition::Operation(parse_operation_definition(parser, schema)?),
),
Token::CurlyOpen
| Token::Name("query")
| Token::Name("mutation")
| Token::Name("subscription") => Ok(Definition::Operation(parse_operation_definition(
parser, schema,
)?)),
Token::Name("fragment") => Ok(Definition::Fragment(parse_fragment_definition(
parser, schema,
)?)),
@ -95,6 +98,7 @@ where
let op = match operation_type.item {
OperationType::Query => Some(schema.concrete_query_type()),
OperationType::Mutation => schema.concrete_mutation_type(),
OperationType::Subscription => schema.concrete_subscription_type(),
};
let fields = op.and_then(|m| m.fields(schema));
let fields = fields.as_ref().map(|c| c as &[_]);
@ -394,6 +398,7 @@ fn parse_operation_type<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Operatio
match parser.peek().item {
Token::Name("query") => Ok(parser.next()?.map(|_| OperationType::Query)),
Token::Name("mutation") => Ok(parser.next()?.map(|_| OperationType::Mutation)),
Token::Name("subscription") => Ok(parser.next()?.map(|_| OperationType::Subscription)),
_ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
}
}

View file

@ -65,6 +65,7 @@ pub struct DirectiveType<'a, S> {
pub enum DirectiveLocation {
Query,
Mutation,
Subscription,
Field,
#[graphql(name = "FRAGMENT_DEFINITION")]
FragmentDefinition,
@ -243,6 +244,18 @@ impl<'a, S> SchemaType<'a, S> {
})
}
pub fn subscription_type(&self) -> Option<TypeType<S>> {
// subscription is not yet in `RootNode`,
// so return `None` for now
None
}
pub fn concrete_subscription_type(&self) -> Option<&MetaType<S>> {
// subscription is not yet in `RootNode`,
// so return `None` for now
None
}
pub fn type_list(&self) -> Vec<TypeType<S>> {
self.types.values().map(|t| TypeType::Concrete(t)).collect()
}
@ -452,6 +465,7 @@ impl fmt::Display for DirectiveLocation {
f.write_str(match *self {
DirectiveLocation::Query => "query",
DirectiveLocation::Mutation => "mutation",
DirectiveLocation::Subscription => "subscription",
DirectiveLocation::Field => "field",
DirectiveLocation::FragmentDefinition => "fragment definition",
DirectiveLocation::FragmentSpread => "fragment spread",

View file

@ -138,9 +138,8 @@ where
self.mutation_type()
}
// Included for compatibility with the introspection query in GraphQL.js
fn subscription_type(&self) -> Option<TypeType<S>> {
None
self.subscription_type()
}
fn directives(&self) -> Vec<&DirectiveType<S>> {

View file

@ -997,6 +997,12 @@ pub(crate) fn schema_introspection_result() -> value::Value {
"isDeprecated": false,
"deprecationReason": Null
},
{
"name": "SUBSCRIPTION",
"description": Null,
"isDeprecated": false,
"deprecationReason": Null
},
{
"name": "FIELD",
"description": Null,
@ -2204,6 +2210,11 @@ pub(crate) fn schema_introspection_result_without_descriptions() -> value::Value
"isDeprecated": false,
"deprecationReason": Null
},
{
"name": "SUBSCRIPTION",
"isDeprecated": false,
"deprecationReason": Null
},
{
"name": "FIELD",
"isDeprecated": false,

View file

@ -28,6 +28,7 @@ where
self.location_stack.push(match op.item.operation_type {
OperationType::Query => DirectiveLocation::Query,
OperationType::Mutation => DirectiveLocation::Mutation,
OperationType::Subscription => DirectiveLocation::Subscription,
});
}
@ -37,7 +38,11 @@ where
_: &'a Spanning<Operation<S>>,
) {
let top = self.location_stack.pop();
assert!(top == Some(DirectiveLocation::Query) || top == Some(DirectiveLocation::Mutation));
assert!(
top == Some(DirectiveLocation::Query)
|| top == Some(DirectiveLocation::Mutation)
|| top == Some(DirectiveLocation::Subscription)
);
}
fn enter_field(&mut self, _: &mut ValidatorContext<'a, S>, _: &'a Spanning<Field<S>>) {

View file

@ -64,6 +64,17 @@ fn visit_definitions<'a, S, V>(
.schema
.concrete_mutation_type()
.map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))),
Definition::Operation(Spanning {
item:
Operation {
operation_type: OperationType::Subscription,
..
},
..
}) => ctx
.schema
.concrete_subscription_type()
.map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))),
};
ctx.with_pushed_type(def_type.as_ref(), |ctx| {

View file

@ -1,6 +1,6 @@
[package]
name = "juniper_codegen"
version = "0.13.2"
version = "0.14.0"
authors = [
"Magnus Hallin <mhallin@fastmail.com>",
"Christoph Herzog <chris@theduke.at>",
@ -21,11 +21,9 @@ async = []
proc-macro2 = "1.0.1"
syn = { version = "1.0.3", features = ["full", "extra-traits", "parsing"] }
quote = "1.0.2"
regex = "1"
lazy_static = "1.0.0"
[dev-dependencies]
juniper = { version = "0.13.1", path = "../juniper" }
juniper = { version = "0.14.0", path = "../juniper" }
[badges]
travis-ci = { repository = "graphql-rust/juniper" }

View file

@ -4,7 +4,7 @@
//! You should not depend on juniper_codegen directly.
//! You only need the `juniper` crate.
#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.13.2")]
#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.14.0")]
#![recursion_limit = "1024"]
extern crate proc_macro;

View file

@ -1,5 +1,4 @@
use quote::quote;
use regex::Regex;
use std::collections::HashMap;
use syn::{
parse, parse_quote, punctuated::Punctuated, Attribute, Lit, Meta, MetaList, MetaNameValue,
@ -279,10 +278,16 @@ pub(crate) fn to_upper_snake_case(s: &str) -> String {
#[doc(hidden)]
pub fn is_valid_name(field_name: &str) -> bool {
lazy_static::lazy_static! {
static ref GRAPHQL_NAME_SPEC: Regex = Regex::new("^[_A-Za-z][_0-9A-Za-z]*$").unwrap();
}
GRAPHQL_NAME_SPEC.is_match(field_name)
let mut chars = field_name.chars();
match chars.next() {
// first char can't be a digit
Some(c) if c.is_ascii_alphabetic() || c == '_' => (),
// can't be an empty string or any other character
_ => return false,
};
chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
}
#[derive(Default, Debug)]

View file

@ -2,6 +2,10 @@
- Compatibility with the latest `juniper`.
# [[0.5.0] 2019-09-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-0.5.0)
- Compatibility with the latest `juniper`.
# [[0.4.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-0.4.1)
- Compatibility with the latest `juniper`.

View file

@ -1,6 +1,6 @@
[package]
name = "juniper_hyper"
version = "0.4.1"
version = "0.5.0"
authors = ["Damir Vandic <info@dvic.io>"]
description = "Juniper GraphQL integration with Hyper"
license = "BSD-2-Clause"
@ -12,8 +12,8 @@ edition = "2018"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
url = "1.7"
juniper = { version = "0.13.1" , default-features = false, path = "../juniper"}
url = "2"
juniper = { version = "0.14.0", default-features = false, path = "../juniper"}
futures = "0.1"
tokio = "0.1.8"
@ -25,6 +25,6 @@ pretty_env_logger = "0.2"
reqwest = "0.9"
[dev-dependencies.juniper]
version = "0.13.1"
version = "0.14.0"
features = ["expose-test-schema", "serde_json"]
path = "../juniper"

View file

@ -27,7 +27,7 @@ fn main() {
let new_service = move || {
let root_node = root_node.clone();
let ctx = db.clone();
service_fn(move |req| -> Box<Future<Item = _, Error = _> + Send> {
service_fn(move |req| -> Box<dyn Future<Item = _, Error = _> + Send> {
let root_node = root_node.clone();
let ctx = ctx.clone();
match (req.method(), req.uri().path()) {

View file

@ -2,6 +2,10 @@
- Compatibility with the latest `juniper`.
# [[0.6.0] 2019-09-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-0.6.0)
- Compatibility with the latest `juniper`.
# [[0.5.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-0.5.1)
- Compatibility with the latest `juniper`.

View file

@ -1,6 +1,6 @@
[package]
name = "juniper_iron"
version = "0.5.1"
version = "0.6.0"
authors = [
"Magnus Hallin <mhallin@fastmail.com>",
"Christoph Herzog <chris@theduke.at>",
@ -15,7 +15,7 @@ edition = "2018"
serde = { version = "1.0.2" }
serde_json = { version = "1.0.2" }
serde_derive = { version = "1.0.2" }
juniper = { version = "0.13.1", path = "../juniper" }
juniper = { version = "0.14.0", path = "../juniper" }
urlencoded = { version = ">= 0.5, < 0.7" }
iron = ">= 0.5, < 0.7"
@ -25,9 +25,10 @@ iron-test = "0.6"
router = "0.6"
mount = "0.4"
logger = "0.4"
url = "1.7.1"
url = "2"
percent-encoding = "2"
[dev-dependencies.juniper]
version = "0.13.1"
version = "0.14.0"
features = ["expose-test-schema", "serde_json"]
path = "../juniper"

View file

@ -431,7 +431,7 @@ mod tests {
use super::*;
use iron::{Handler, Headers, Url};
use iron_test::{request, response};
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
use juniper::{
http::tests as http_tests,
@ -441,6 +441,9 @@ mod tests {
use super::GraphQLHandler;
/// https://url.spec.whatwg.org/#query-state
const QUERY_ENCODE_SET: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b'#').add(b'<').add(b'>');
// This is ugly but it works. `iron_test` just dumps the path/url in headers
// and newer `hyper` doesn't allow unescaped "{" or "}".
fn fixup_url(url: &str) -> String {
@ -454,7 +457,7 @@ mod tests {
format!(
"http://localhost:3000{}?{}",
path,
utf8_percent_encode(url.query().unwrap_or(""), DEFAULT_ENCODE_SET)
utf8_percent_encode(url.query().unwrap_or(""), QUERY_ENCODE_SET)
)
}
@ -521,7 +524,7 @@ mod tests {
}
}
fn make_handler() -> Box<Handler> {
fn make_handler() -> Box<dyn Handler> {
Box::new(GraphQLHandler::new(
context_factory,
Query,

View file

@ -2,6 +2,10 @@
- Compatibility with the latest `juniper`.
# [[0.5.0] 2019-09-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_rocket-0.5.0)
- Compatibility with the latest `juniper`.
# [[0.4.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_rocket-0.4.1)
- Compatibility with the latest `juniper`.

View file

@ -1,6 +1,6 @@
[package]
name = "juniper_rocket"
version = "0.4.1"
version = "0.5.0"
authors = [
"Magnus Hallin <mhallin@fastmail.com>",
"Christoph Herzog <chris@theduke.at>",
@ -18,13 +18,13 @@ async = [ "juniper/async" ]
serde = { version = "1.0.2" }
serde_json = { version = "1.0.2" }
serde_derive = { version = "1.0.2" }
juniper = { version = "0.13.1" , default-features = false, path = "../juniper"}
juniper = { version = "0.14.0", default-features = false, path = "../juniper"}
futures03 = { version = "=0.3.0-alpha.19", package = "futures-preview", features = ["compat"] }
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "async" }
tokio = "=0.2.0-alpha.6"
[dev-dependencies.juniper]
version = "0.13.1"
version = "0.14.0"
features = ["expose-test-schema", "serde_json"]
path = "../juniper"

View file

@ -2,6 +2,10 @@
- Compatibility with the latest `juniper`.
# [[0.5.0] 2019-09-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_warp-0.5.0)
- Compatibility with the latest `juniper`.
# [[0.4.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper_warp-0.4.1)
- Compatibility with the latest `juniper`.

View file

@ -1,6 +1,6 @@
[package]
name = "juniper_warp"
version = "0.4.1"
version = "0.5.0"
authors = ["Tom Houlé <tom@tomhoule.com>"]
description = "Juniper GraphQL integration with Warp"
license = "BSD-2-Clause"
@ -13,7 +13,7 @@ async = [ "juniper/async", "futures03" ]
[dependencies]
warp = "0.1.8"
juniper = { version = "0.13.1", path = "../juniper" }
juniper = { version = "0.14.0", path = "../juniper", default-features = false }
serde_json = "1.0.24"
serde_derive = "1.0.75"
failure = "0.1.2"
@ -24,7 +24,7 @@ tokio-threadpool = "0.1.7"
futures03 = { version = "=0.3.0-alpha.19", optional = true, package = "futures-preview", features = ["compat"] }
[dev-dependencies]
juniper = { version = "0.13.1", path = "../juniper", features = ["expose-test-schema", "serde_json"] }
juniper = { version = "0.14.0", path = "../juniper", features = ["expose-test-schema", "serde_json"] }
env_logger = "0.5.11"
log = "0.4.3"
percent-encoding = "1.0"