Releases: apollographql/apollo-rs
[email protected] (#762)
BREAKING
-
API refactor to make it harder to ignore errors - SimonSapin, pull/752 fixing issue/709:
ast::Document
,Schema
, andExecutableDocument
not longer contain potential errors
that users need to check separately.- Instead, various constructors and methods now return a
Result
,
with theErr
case containing both both errors and a maybe-incomplete value. - Change
validate
methods ofSchema
andExecutableDocument
to take ownership ofself
.
On success they return the schema or document (unmodified) wrapped in aValid<_>
marker type,
which is immutable. - Change
ExecutableDocument
to require a&Valid<Schema>
instead of&Schema
,
forcing callers to either run validation or opt out explicitly withValid::assume_valid
. - Make
parse_mixed
andto_mixed
validate both the schema and document.
Rename them with a_validate
suffix. - Corresponding changes to all of the above in
Parser
method signatures - Remove
ast::Document::check_parse_errors
:
parse errors are now encoded in the return value ofparse
. - Remove
ast::Document::to_schema_builder
. UseSchemaBuilder::add_ast
instead. - Move items from the crate top-level to
apollo_compiler::validation
:Diagnostic
DiagnosticList
FileId
NodeLocation
- Move items from the crate top-level to
apollo_compiler::execution
:GraphQLError
GraphQLLocation
- Remove warning-level and advice-level diagnostics. See issue/751.
Highlight of signature changes:
+struct Valid<T>(T); // Implements `Deref` and `AsRef` but not `DerefMut` or `AsMut` + +struct WithErrors<T> { + partial: T, // Errors may cause components to be missing + errors: DiagnosticList, +} -pub fn parse_mixed(…) -> (Schema, ExecutableDocument) +pub fn parse_mixed_validate(…) + -> Result<(Valid<Schema>, Valid<ExecutableDocument>), DiagnosticList> impl ast::Document { - pub fn parse(…) -> Self + pub fn parse(…) -> Result<Self, WithErrors<Self>> - pub fn to_schema(&self) -> Schema + pub fn to_schema(&self) -> Result<Schema, WithErrors<Schema>> - pub fn to_executable(&self) -> ExecutableDocument + pub fn to_executable(&self) -> Result<ExecutableDocument, WithErrors<ExecutableDocument>> - pub fn to_mixed(&self) -> (Schema, ExecutableDocument) + pub fn to_mixed_validate( + &self, + ) -> Result<(Valid<Schema>, Valid<ExecutableDocument>), DiagnosticList> } impl Schema { - pub fn parse(…) -> Self - pub fn validate(&self) -> Result<DiagnosticList, DiagnosticList> + pub fn parse_and_validate(…) -> Result<Valid<Self>, WithErrors<Self>> + pub fn parse(…) -> Result<Self, WithErrors<Self>> + pub fn validate(self) -> Result<Valid<Self>, WithErrors<Self>> } impl SchemaBuilder { - pub fn build(self) -> Schema + pub fn build(self) -> Result<Schema, WithErrors<Schema>> } impl ExecutableDocument { - pub fn parse(schema: &Schema, …) -> Self - pub fn validate(&self, schema: &Schema) -> Result<(), DiagnosticList> + pub fn parse_and_validate(schema: &Valid<Schema>, …) -> Result<Valid<Self>, WithErrors<Self>> + pub fn parse(schema: &Valid<Schema>, …) -> Result<Self, WithErrors<Self>> + pub fn validate(self, schema: &Valid<Schema>) -> Result<Valid<Self>, WithErrors<Self>> }
Features
-
Add
parse_and_validate
constructors forSchema
andExecutableDocument
- SimonSapin, pull/752:
when mutating isn’t needed after parsing, this returns an immutableValid<_>
value in one step. -
Implement serde
Serialize
andDeserialize
for some AST types - SimonSapin, pull/760:Node
NodeStr
Name
IntValue
FloatValue
Value
Type
Source locations are not preserved through serialization.
-
Add
ast::Definition::as_*() -> Option<&_>
methods for each variant - SimonSapin, pull/760 -
Serialize (to GraphQL) multi-line strings as block strings - SimonSapin, pull/724:
Example before:"Example\n\nDescription description description" schema { query: MyQuery }
After:
""" Example Description description description """ schema { query: MyQuery }
Fixes
-
Limit recursion in validation - goto-bus-stop, pull/748 fixing issue/742:
Validation now bails out of very long chains of definitions that refer to each other,
even if they don't strictly form a cycle. These could previously cause extremely long validation
times or stack overflows.The limit for input objects and directives is set at 32. For fragments, the limit is set at 100.
Based on our datasets, real-world documents don't come anywhere close to this.
[email protected]
Features
parse_type
parses a selection set with optional outer brackets - lrlna, pull/718 fixing issue/715
This returns aSyntaxTree<Type>
which instead of.document() -> cst::Document
has.type() -> cst::Type
.
This is intended to parse the string value of a@field(type:)
argument
used in some Apollo Federation directives.let source = r#"[[NestedList!]]!"#; let parser = Parser::new(source); let cst: SyntaxTree<cst::Type> = parser.parse_type(); let errors = cst.errors().collect::<Vec<_>>(); assert_eq!(errors.len(), 0);
Fixes
-
Input object values can be empty - goto-bus-stop, pull/745 fixing issue/744
apollo-parser
version 0.7.3 introduced a regression where empty input objects failed to parse.
This is now fixed.{ field(argument: {}) }
[email protected]
Features
- Helper features for
Name
andType
- SimonSapin, pull/739:- The
name!
macro also accepts an identifier:
name!(Query)
andname!("Query")
create equivalentName
values. InvalidNameError
now contain a publicNodeStr
for the input string that is invalid,
and implementsDisplay
,Debug
, andError
traits.- Add
TryFrom
conversion toName
fromNodeStr
,&NodeStr
,&str
,String
, and&String
. - Add a
ty!
macro to build a staticast::Type
using GraphQL-like syntax.
- The
-
Add parsing an
ast::Type
from a string - lrlna and goto-bus-stop, pull/718 fixing issue/715Parses GraphQL type syntax:
use apollo_compiler::ast::Type; let ty = Type::parse("[ListItem!]!")?;
Fixes
-
Fix list and null type validation bugs - goto-bus-stop, pull/746 fixing issue/738
Previous versions of apollo-compiler acceptednull
inside a list even if the list item type
was marked as required. Lists were also accepted as inputs to non-list fields. This is now
fixed.input Args { string: String ints: [Int!] } type Query { example(args: Args): Int } query { example(args: { # Used to be accepted, now raises an error string: ["1"] # Used to be accepted, now raises an error ints: [1, 2, null, 4] }) }
[email protected]
BREAKING
-
Make everything know their own name - SimonSapin, pull/727 fixing issue/708.
In a few places (but not consistently) a
name
field
was omitted from some structs used as map values
on the basis that it would have been redundant with the map key.
This reverts that decision,
making it the user’s responsibility when mutating documents to keep names consistent.- Add a
pub name: Name
field toexecutable::Fragment
as well as
ScalarType
,ObjectType
,InterfaceType
,EnumType
,UnionType
, andInputObjectType
inschema
. - Add a
fn name(&self) -> &Name
method to theschema::ExtendedType
enum - Add a
pub name: Option<Name>
field toexecutable::Operation
- Remove
executable::OperationRef<'_>
(which was equivalent to(Option<&Name>, &Node<Operation>)
),
replacing its uses with&Node<Operation>
- Add a
-
Rename
Directives
andDiagnostics
toDirectiveList
andDiagnosticList
-
SimonSapin, pull/732 fixing issue/711.
The previous names were too similar toDirective
andDiagnostic
(singular). -
Rename
ComponentStr
toComponentName
- SimonSapin, pull/713
and itsnode: NodeStr
field toname: Name
. -
Assorted changed to GraphQL names - SimonSapin, pull/713 fixing issue/710.
- Check validity of
ast::Name
.
NodeStr
is a smart string type with infallible conversion from&str
.
ast::Name
used to be a type alias forNodeStr
,
leaving the possibility of creating one invalid in GraphQL syntax.
Validation and serialization would not check this.
Name
is now a wrapper type forNodeStr
.
Itsnew
constructor checks validity of the given string and returns aResult
.
A newname!
macro (see below) creates aName
with compile-time checking. OperationType::default_type_name
returns aName
instead of&str
Type::new_named("x")
is removed. UseType::Named(name!("x"))
instead.ComponentStr
is renamed toComponentName
.
It no longer has infallible conversions from&str
orString
.
Itsnode
field is renamed toname
;
the type of that field is changed fromNodeStr
toName
.NodeStr
no longer has ato_component
method, onlyName
does- Various function or method parameters changed from
impl Into<Name>
toName
,
since there is no longer an infallible conversion from&str
- Check validity of
Features
-
Add serialization support for everything - SimonSapin, pull/728.
Schema
,ExecutableDocument
, and all AST types
already supported serialization to GraphQL syntax
through theDisplay
trait and the.serialize()
method.
This is now also the case of all other Rust types
representing some element of a GraphQL document:schema::Directives
schema::ExtendedType
schema::ScalarType
schema::ObjectType
schema::InterfaceType
schema::EnumType
schema::UnionType
schema::InputObjectType
executable::Operation
executable::Fragment
executable::SelectionSet
executable::Selection
executable::Field
executable::InlineFragment
executable::FragmentSpread
executable::FieldSet
-
Assorted changed to GraphQL names - SimonSapin, pull/713 fixing issue/710.
See also the BREAKING section above.- Add a
name!("example")
macro,
to be imported withuse apollo_compiler::name;
.
It creates anast::Name
from a string literal, with a compile-time validity checking.
AName
created this way does not own allocated heap memory or a reference counter,
so cloning it is extremely cheap. - Add allocation-free
NodeStr::from_static
.
This mostly exists to support thename!
macro, but can also be used on its own:let s = apollo_compiler::NodeStr::from_static(&"example"); assert_eq!(s, "example");
- Add a
Fixes
- Fix crash in validation of self-referential fragments - goto-bus-stop, pull/733 fixing issue/716.
Now fragments that cyclically reference themselves inside a nested field also produce a
validation error, instead of causing a stack overflow crash.
[email protected]
0.7.3 - 2023-11-07
Fixes
-
Less recursion in parser implementation - goto-bus-stop, pull/721 fixing issue/666
The parser previously used recursive functions while parsing some repetitive nodes, like members of an enum:enum Alphabet { A B C D E F G etc }
Even though this is a flat list, each member would use a recursive call. Having many members, or fields in a type
definition, or arguments in a directive, would all contribute to the recursion limit.Those cases are now using iteration instead and no longer contribute to the recursion limit. The default recursion limit
is unchanged at 500, but you could reduce it depending on your needs.
- Fix overly permissive parsing of
implements
lists andunion
member types - goto-bus-stop, pull/721 fixing issue/659
Previously these definitions were all accepted, despite missing or excessive&
and|
separators:Now they report a syntax error.type Ty implements A B type Ty implements A && B type Ty implements A & B & union Ty = A B union Ty = A || B union Ty = A | B |
[email protected]
0.7.2 - 2023-11-03
Fixes
- Fix
SyntaxTree
being accidentally!Send
and!Sync
- SimonSapin, pull/704 fixing issue/702
[email protected]
1.0.0-beta.4 - 2023-10-16
Features
-
JSON Serialisable compiler diagnostics - lrlna and goto-bus-stop, pull/698:
This change brings back JSON error format for diagnostics introduced by goto-bus-stop in pull/668 for [email protected]. As a result, diagnostics' line/column numbers are now also accessible as part of the public API.let json = expect_test::expect![[r#" { "message": "an executable document must not contain an object type definition", "locations": [ { "line": 2, "column": 1 } ] }"#]]; let diagnostics = executable.validate(&schema).unwrap_err(); diagnostics.iter().for_each(|diag| { assert_eq!( diag.get_line_column(), Some(GraphQLLocation { line: 2, column: 1 }) ); json.assert_eq(&serde_json::to_string_pretty(&diag.to_json()).unwrap()); });
Fixes
- Don’t emit a validation error for relying on argument default - SimonSapin, pull/700
A field argument or directive argument was incorrectly considered required as soon as it had a non-null type, even if it had a default value.
[email protected]
1.0.0-beta.3 - 2023-10-13
BREAKING
- Keep source files in
Arc<Map<…>>
everywhere - SimonSapin, pull/696:
Change struct fields fromsources: IndexMap<FileId, Arc<SourceFile>>
(inSchema
) orsource: Option<(FileId, Arc<SourceFile>)>
(inDocument
,ExecutablDocument
,FieldSet
) tosources: SourceMap
, with:Cases other thanpub type SourceMap = Arc<IndexMap<FileId, Arc<SourceFile>>>;
Schema
still only have zero or one source when created by apollo-compiler, but it is now possible to make more sources available to diagnostics, for example when merging documents:Arc::make_mut(&mut doc1.sources).extend(doc2.sources.iter().map(|(k, v)| (*k, v.clone())));
Features
- Add iteration over individual diagnostics - SimonSapin, pull/696:
let schema = Schema::parse(input, "schema.graphql"); if let Err(errors) = schema.validate() { for error in errors.iter() { eprintln!("{error}") } }
Fixes
- Don’t panic in validation or omit diagnostics when a source location is missing - SimonSapin, pull/697:
In apollo-compiler 0.11 every element of the HIR always had a source location because it always came from a parsed input file. In 1.0 source location is always optional. When a node relevant to some diagnostic does not have a source location, the diagnostic should still be emitted but its labels (each printing a bit of source code) may be missing. Essential information should therefore be in the main message, not only in labels.
[email protected]
0.7.1 - 2023-10-10
Features
parse_field_set
parses a selection set with optional outer brackets - lrlna, pull/685 fixing issue/681
This returns aSyntaxTree<SelectionSet>
which instead of.document() -> cst::Document
has.field_set() -> cst::SelectionSet
.
This is intended to parse string value of aFieldSet
custom scalar
used in some Apollo Federation directives.let source = r#"a { a }"#; let parser = Parser::new(source); let cst: SyntaxTree<cst::SelectionSet> = parser.parse_selection_set(); let errors = cst.errors().collect::<Vec<_>>(); assert_eq!(errors.len(), 0);
[email protected]
1.0.0-beta.2 - 2023-10-10
BREAKING
Assorted Schema
API changes by SimonSapin in pull/678:
- Type of the
schema_definition
field changed
fromOption<SchemaDefinition>
toSchemaDefinition
.
Default root operations based on object type names
are now stored explicitly inSchemaDefinition
.
Serialization relies on a heuristic to decide on implicit schema definition. - Removed
schema_definition_directives
method: no longer having anOption
allows
fieldschema.schema_definition.directives
to be accessed directly - Removed
query_root_operation
,mutation_root_operation
, andsubscription_root_operation
methods. Insteadschema.schema_definition.query
etc can be accessed directly.
Features
-
Add
executable::FieldSet
for a selection set with optional outer brackets - lrlna, pull/685 fixing issue/681
This is intended to parse string value of aFieldSet
custom scalar
used in some Apollo Federation directives in the context of a specific schema and type.
Itsvalidate
method calls a subset of validation rules relevant to selection sets.
which is not part of a document.let input = r#" type Query { id: ID organization: Org } type Org { id: ID } "#; let schema = Schema::parse(input, "schema.graphql"); schema.validate().unwrap(); let input = "id organization { id }"; let field_set = FieldSet::parse(&schema, "Query", input, "field_set.graphql"); field_set.validate(&schema).unwrap();
-
Add opt-in configuration for “orphan” extensions to be “adopted” - SimonSapin, pull/678
Type extensions and schema extensions without a corresponding definition
are normally ignored except for recording a validation error.
In this new mode, an implicit empty definition to extend is generated instead.
This behavious is not the default, as it's non-standard.
Configure a schema builder to opt in:let input = "extend type Query { x: Int }"; let schema = apollo_compiler::Schema::builder() .adopt_orphan_extensions() .parse(input, "schema.graphql") .build(); schema.validate()?;
Fixes
- Allow built-in directives to be redefined - SimonSapin, pull/684 fixing issue/656
- Allow schema extensions to extend a schema definition implied by object types named after default root operations - SimonSapin, pull/678 fixing [issues/682]