diff --git a/src/HotChocolate/MongoDb/src/Types/BsonType.cs b/src/HotChocolate/MongoDb/src/Types/BsonType.cs
new file mode 100644
index 00000000000..6087d072ce0
--- /dev/null
+++ b/src/HotChocolate/MongoDb/src/Types/BsonType.cs
@@ -0,0 +1,396 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using HotChocolate.Configuration;
+using HotChocolate.Language;
+using HotChocolate.Types.MongoDb.Resources;
+using HotChocolate.Utilities;
+using MongoDB.Bson;
+
+namespace HotChocolate.Types.MongoDb;
+
+///
+/// BSON is a binary format in which zero or more ordered key/value pairs are stored as a single
+/// entity.
+/// The results are returned as JSON objects
+///
+public class BsonType : ScalarType
+{
+ private ITypeConverter _converter = default!;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BsonType()
+ : this(
+ MongoDbScalarNames.Bson,
+ MongoDbTypesResources.Bson_Type_Description,
+ BindingBehavior.Implicit)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BsonType(
+ NameString name,
+ string? description = null,
+ BindingBehavior bind = BindingBehavior.Explicit)
+ : base(name, bind)
+ {
+ SpecifiedBy = new Uri("https://bsonspec.org/spec.html");
+ Description = description;
+ }
+
+ ///
+ public override Type RuntimeType => typeof(BsonValue);
+
+ ///
+ protected override void OnCompleteType(
+ ITypeCompletionContext context,
+ IDictionary contextData)
+ {
+ _converter = context.Services.GetTypeConverter();
+ base.OnCompleteType(context, contextData);
+ }
+
+ ///
+ public override bool IsInstanceOfType(IValueNode valueSyntax)
+ {
+ if (valueSyntax is null)
+ {
+ throw new ArgumentNullException(nameof(valueSyntax));
+ }
+
+ switch (valueSyntax)
+ {
+ case StringValueNode:
+ case IntValueNode:
+ case FloatValueNode:
+ case BooleanValueNode:
+ case ListValueNode:
+ case ObjectValueNode:
+ case NullValueNode:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private BsonValue? ParseLiteralToBson(IValueNode literal)
+ {
+ switch (literal)
+ {
+ case StringValueNode svn:
+ return new BsonString(svn.Value);
+
+ case IntValueNode ivn:
+ return new BsonInt64(long.Parse(ivn.Value, CultureInfo.InvariantCulture));
+
+ case FloatValueNode fvn
+ when double.TryParse(fvn.Value,
+ NumberStyles.Float | NumberStyles.Integer,
+ CultureInfo.InvariantCulture,
+ out double f):
+ return new BsonDouble(f);
+
+ case FloatValueNode fvn:
+ return new BsonDecimal128(
+ decimal.Parse(fvn.Value, CultureInfo.InvariantCulture));
+
+ case BooleanValueNode bvn:
+ return new BsonBoolean(bvn.Value);
+
+ case ListValueNode lvn:
+ BsonValue?[] values = new BsonValue[lvn.Items.Count];
+ for (var i = 0; i < lvn.Items.Count; i++)
+ {
+ values[i] = ParseLiteralToBson(lvn.Items[i]);
+ }
+
+ return new BsonArray(values);
+
+ case ObjectValueNode ovn:
+ BsonDocument document = new();
+ foreach (ObjectFieldNode field in ovn.Fields)
+ {
+ document.Add(field.Name.Value, ParseLiteralToBson(field.Value));
+ }
+
+ return document;
+
+ case NullValueNode:
+ return BsonNull.Value;
+
+ default:
+ throw ThrowHelper.Bson_CouldNotParseLiteral(this, literal);
+ }
+ }
+
+ ///
+ public override object? ParseLiteral(IValueNode valueSyntax)
+ {
+ return ParseLiteralToBson(valueSyntax);
+ }
+
+ ///
+ public override IValueNode ParseValue(object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return NullValueNode.Default;
+ }
+
+ if (runtimeValue is not BsonValue value)
+ {
+ value = BsonTypeMapper.MapToBsonValue(runtimeValue);
+ }
+
+ switch (value)
+ {
+ case BsonString s:
+ return new StringValueNode(s.Value);
+
+ case BsonInt32 i:
+ return new IntValueNode(i.Value);
+
+ case BsonInt64 l:
+ return new IntValueNode(l.Value);
+
+ case BsonDouble f:
+ return new FloatValueNode(f.Value);
+
+ // The range of Decimal128 is different. Therefor we have to serialize
+ // it as a string, or else information loss could occure
+ // see https://jira.mongodb.org/browse/CSHARP-2210
+ case BsonDecimal128 d:
+ return new StringValueNode(d.Value.ToString());
+
+ case BsonBoolean b:
+ return new BooleanValueNode(b.Value);
+
+ case BsonObjectId s:
+ return new StringValueNode(s.Value.ToString());
+
+ case BsonDateTime dateTime when _converter
+ .TryConvert(dateTime.ToNullableUniversalTime(), out string formatedDateTime):
+ return new StringValueNode(formatedDateTime);
+
+ case BsonBinaryData bd:
+ return new StringValueNode(Convert.ToBase64String(bd.Bytes));
+
+ case BsonTimestamp timeStamp:
+ return new IntValueNode(timeStamp.Value);
+ }
+
+ if (value is BsonDocument doc)
+ {
+ List fields = new();
+ foreach (BsonElement field in doc)
+ {
+ fields.Add(new ObjectFieldNode(field.Name, ParseValue(field.Value)));
+ }
+
+ return new ObjectValueNode(fields);
+ }
+
+ if (value is BsonArray arr)
+ {
+ List valueList = new();
+ foreach (BsonValue element in arr)
+ {
+ valueList.Add(ParseValue(element));
+ }
+
+ return new ListValueNode(valueList);
+ }
+
+ var mappedValue = BsonTypeMapper.MapToDotNetValue(value);
+ Type type = mappedValue.GetType();
+
+ if (type.IsValueType &&
+ _converter.TryConvert(type, typeof(string), mappedValue, out object? converted) &&
+ converted is string c)
+ {
+ return new StringValueNode(c);
+ }
+
+ throw ThrowHelper.Bson_CouldNotParseValue(this, runtimeValue);
+ }
+
+ ///
+ public override IValueNode ParseResult(object? resultValue) =>
+ ParseValue(resultValue);
+
+ public override bool TrySerialize(object? runtimeValue, out object? resultValue)
+ {
+ resultValue = null;
+ if (runtimeValue is null or BsonNull)
+ {
+ return true;
+ }
+
+ switch (runtimeValue)
+ {
+ case BsonArray arr:
+ object?[] res = new object?[arr.Count];
+ for (var i = 0; i < arr.Count; i++)
+ {
+ if (!TrySerialize(arr[i], out var s))
+ {
+ return false;
+ }
+
+ res[i] = s;
+ }
+
+ resultValue = res;
+ return true;
+
+ case BsonDocument doc:
+ Dictionary docRes = new();
+ foreach (BsonElement element in doc)
+ {
+ if (!TrySerialize(element.Value, out var s))
+ {
+ return false;
+ }
+
+ docRes[element.Name] = s;
+ }
+
+ resultValue = docRes;
+ return true;
+
+ case BsonDateTime dateTime:
+ DateTime? parsedDateTime = dateTime.ToNullableUniversalTime();
+ if (_converter.TryConvert(parsedDateTime, out string? formatedDateTime))
+ {
+ resultValue = formatedDateTime;
+ return true;
+ }
+
+ return false;
+
+ case BsonTimestamp timeStamp:
+ resultValue = timeStamp.Value;
+ return true;
+
+ case BsonObjectId objectId:
+ resultValue = objectId.Value.ToString();
+ return true;
+
+ case BsonString s:
+ resultValue = s.Value;
+ return true;
+
+ case BsonInt32 i:
+ resultValue = i.Value;
+ return true;
+
+ case BsonInt64 l:
+ resultValue = l.Value;
+ return true;
+
+ case BsonDouble f:
+ resultValue = f.Value;
+ return true;
+
+ case BsonBinaryData bd:
+ resultValue = Convert.ToBase64String(bd.Bytes);
+ return true;
+
+ // The range of Decimal128 is different. Therefor we have to serialize
+ // it as a string, or else information loss could occure
+ // see https://jira.mongodb.org/browse/CSHARP-2210
+ case BsonDecimal128 d:
+ resultValue = d.Value.ToString();
+ return true;
+
+ case BsonBoolean b:
+ resultValue = b.Value;
+ return true;
+
+ case BsonValue a:
+ var dotNetValue = BsonTypeMapper.MapToDotNetValue(a);
+
+ Type type = dotNetValue.GetType();
+
+ if (type.IsValueType &&
+ _converter.TryConvert(type, typeof(string), dotNetValue, out object? c) &&
+ c is string casted)
+ {
+ resultValue = casted;
+ return true;
+ }
+
+ resultValue = null;
+ return false;
+
+ case IValueNode literal:
+ resultValue = ParseLiteral(literal);
+ return true;
+
+ default:
+ resultValue = null;
+ return false;
+ }
+ }
+
+ ///
+ public override bool TryDeserialize(object? resultValue, out object? runtimeValue)
+ {
+ object? elementValue;
+ runtimeValue = null;
+ switch (resultValue)
+ {
+ case IDictionary dictionary:
+ {
+ var result = new BsonDocument();
+ foreach (KeyValuePair element in dictionary)
+ {
+ if (TryDeserialize(element.Value, out elementValue))
+ {
+ result[element.Key] = (BsonValue)elementValue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ runtimeValue = result;
+ return true;
+ }
+
+ case IList list:
+ {
+ var result = new BsonValue[list.Count];
+ for (var i = 0; i < list.Count; i++)
+ {
+ if (TryDeserialize(list[i], out elementValue))
+ {
+ result[i] = (BsonValue)elementValue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ runtimeValue = new BsonArray(result);
+ return true;
+ }
+
+ case IValueNode literal:
+ runtimeValue = ParseLiteral(literal);
+ return true;
+
+ default:
+ runtimeValue = BsonTypeMapper.MapToBsonValue(resultValue);
+ return true;
+ }
+ }
+}
diff --git a/src/HotChocolate/MongoDb/src/Types/HotChocolate.Types.MongoDb.csproj b/src/HotChocolate/MongoDb/src/Types/HotChocolate.Types.MongoDb.csproj
index c986cf7f43b..de617ea6df4 100644
--- a/src/HotChocolate/MongoDb/src/Types/HotChocolate.Types.MongoDb.csproj
+++ b/src/HotChocolate/MongoDb/src/Types/HotChocolate.Types.MongoDb.csproj
@@ -10,6 +10,7 @@
+
diff --git a/src/HotChocolate/MongoDb/src/Types/MongoDbScalarNames.cs b/src/HotChocolate/MongoDb/src/Types/MongoDbScalarNames.cs
index 93e9cd34f7f..7612f11c70c 100644
--- a/src/HotChocolate/MongoDb/src/Types/MongoDbScalarNames.cs
+++ b/src/HotChocolate/MongoDb/src/Types/MongoDbScalarNames.cs
@@ -11,5 +11,11 @@ public static class MongoDbScalarNames
/// sequences.
///
public static readonly string ObjectId = nameof(ObjectId);
+
+ ///
+ /// The name of the Bson scalar type.
+ /// sequences.
+ ///
+ public static readonly string Bson = nameof(Bson);
}
}
diff --git a/src/HotChocolate/MongoDb/src/Types/MongoDbTypesRequestExecutorExtensions.cs b/src/HotChocolate/MongoDb/src/Types/MongoDbTypesRequestExecutorExtensions.cs
new file mode 100644
index 00000000000..c4f56101374
--- /dev/null
+++ b/src/HotChocolate/MongoDb/src/Types/MongoDbTypesRequestExecutorExtensions.cs
@@ -0,0 +1,27 @@
+using HotChocolate;
+using HotChocolate.Execution.Configuration;
+using HotChocolate.Types.MongoDb;
+
+namespace Microsoft.Extensions.DependencyInjection;
+
+///
+/// Common extension of for MongoDb types
+///
+public static class MongoDbTypesRequestExecutorBuilderExtensions
+{
+ ///
+ /// Registers on the schema
+ ///
+ /// The request executor builder
+ /// The request executor builder
+ public static IRequestExecutorBuilder AddObjectIdType(this IRequestExecutorBuilder builder) =>
+ builder.ConfigureSchema(x => x.AddObjectIdType());
+
+ ///
+ /// Registers and binds the BSON subtypes to the scalar
+ ///
+ /// The request executor builder
+ /// The request executor builder
+ public static IRequestExecutorBuilder AddBsonType(this IRequestExecutorBuilder builder) =>
+ builder.ConfigureSchema(x => x.AddBsonType());
+}
diff --git a/src/HotChocolate/MongoDb/src/Types/MongoDbTypesSchemaBuilderExtensions.cs b/src/HotChocolate/MongoDb/src/Types/MongoDbTypesSchemaBuilderExtensions.cs
new file mode 100644
index 00000000000..6670b7fa146
--- /dev/null
+++ b/src/HotChocolate/MongoDb/src/Types/MongoDbTypesSchemaBuilderExtensions.cs
@@ -0,0 +1,48 @@
+using HotChocolate.Types.MongoDb;
+using MongoDB.Bson;
+using BsonType = HotChocolate.Types.MongoDb.BsonType;
+
+namespace HotChocolate;
+
+///
+/// Common extension of for MongoDb types
+///
+public static class MongoDbTypesSchemaBuilderExtensions
+{
+ ///
+ /// Registers on the schema
+ ///
+ /// The schema builder
+ /// The schema builder
+ public static ISchemaBuilder AddObjectIdType(this ISchemaBuilder builder)
+ {
+ builder.AddType();
+ return builder;
+ }
+
+ ///
+ /// Registers and binds the BSON subtypes to the scalar
+ ///
+ /// The schema builder
+ /// The schema builder
+ public static ISchemaBuilder AddBsonType(this ISchemaBuilder builder)
+ {
+ builder.AddType();
+ builder.BindRuntimeType(typeof(BsonValue), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonArray), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonDocument), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonBoolean), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonDouble), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonDecimal128), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonDateTime), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonTimestamp), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonObjectId), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonBinaryData), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonInt32), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonInt64), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonNull), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonBoolean), typeof(BsonType));
+ builder.BindRuntimeType(typeof(BsonString), typeof(BsonType));
+ return builder;
+ }
+}
diff --git a/src/HotChocolate/MongoDb/src/Types/ObjectIdType.cs b/src/HotChocolate/MongoDb/src/Types/ObjectIdType.cs
index 6645f0be2cc..3ce82b53d04 100644
--- a/src/HotChocolate/MongoDb/src/Types/ObjectIdType.cs
+++ b/src/HotChocolate/MongoDb/src/Types/ObjectIdType.cs
@@ -21,7 +21,6 @@ public ObjectIdType()
MongoDbTypesResources.ObjectId_Type_Description,
BindingBehavior.Implicit)
{
- SpecifiedBy = new Uri("https://docs.mongodb.com/manual/reference/bson-types/#objectid");
}
///
@@ -33,6 +32,7 @@ public ObjectIdType(
BindingBehavior bind = BindingBehavior.Explicit)
: base(name, bind)
{
+ SpecifiedBy = new Uri("https://docs.mongodb.com/manual/reference/bson-types/#objectid");
Description = description;
}
diff --git a/src/HotChocolate/MongoDb/src/Types/PublicAPI.Unshipped.txt b/src/HotChocolate/MongoDb/src/Types/PublicAPI.Unshipped.txt
index e69de29bb2d..f1a653ce01c 100644
--- a/src/HotChocolate/MongoDb/src/Types/PublicAPI.Unshipped.txt
+++ b/src/HotChocolate/MongoDb/src/Types/PublicAPI.Unshipped.txt
@@ -0,0 +1,18 @@
+HotChocolate.MongoDbTypesSchemaBuilderExtensions
+HotChocolate.Types.MongoDb.BsonType
+HotChocolate.Types.MongoDb.BsonType.BsonType() -> void
+HotChocolate.Types.MongoDb.BsonType.BsonType(HotChocolate.NameString name, string? description = null, HotChocolate.Types.BindingBehavior bind = HotChocolate.Types.BindingBehavior.Explicit) -> void
+Microsoft.Extensions.DependencyInjection.MongoDbTypesRequestExecutorBuilderExtensions
+override HotChocolate.Types.MongoDb.BsonType.IsInstanceOfType(HotChocolate.Language.IValueNode! literal) -> bool
+override HotChocolate.Types.MongoDb.BsonType.OnCompleteType(HotChocolate.Configuration.ITypeCompletionContext! context, System.Collections.Generic.IDictionary! contextData) -> void
+override HotChocolate.Types.MongoDb.BsonType.ParseLiteral(HotChocolate.Language.IValueNode! literal) -> object?
+override HotChocolate.Types.MongoDb.BsonType.ParseResult(object? resultValue) -> HotChocolate.Language.IValueNode!
+override HotChocolate.Types.MongoDb.BsonType.ParseValue(object? val) -> HotChocolate.Language.IValueNode!
+override HotChocolate.Types.MongoDb.BsonType.RuntimeType.get -> System.Type!
+override HotChocolate.Types.MongoDb.BsonType.TryDeserialize(object? resultValue, out object? runtimeValue) -> bool
+override HotChocolate.Types.MongoDb.BsonType.TrySerialize(object? runtimeValue, out object? resultValue) -> bool
+static HotChocolate.MongoDbTypesSchemaBuilderExtensions.AddBsonType(this HotChocolate.ISchemaBuilder! builder) -> HotChocolate.ISchemaBuilder!
+static HotChocolate.MongoDbTypesSchemaBuilderExtensions.AddObjectIdType(this HotChocolate.ISchemaBuilder! builder) -> HotChocolate.ISchemaBuilder!
+static Microsoft.Extensions.DependencyInjection.MongoDbTypesRequestExecutorBuilderExtensions.AddBsonType(this HotChocolate.Execution.Configuration.IRequestExecutorBuilder! builder) -> HotChocolate.Execution.Configuration.IRequestExecutorBuilder!
+static Microsoft.Extensions.DependencyInjection.MongoDbTypesRequestExecutorBuilderExtensions.AddObjectIdType(this HotChocolate.Execution.Configuration.IRequestExecutorBuilder! builder) -> HotChocolate.Execution.Configuration.IRequestExecutorBuilder!
+static readonly HotChocolate.Types.MongoDb.MongoDbScalarNames.Bson -> string!
\ No newline at end of file
diff --git a/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.Designer.cs b/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.Designer.cs
index c0e0e7c192f..66c02cb1a1e 100644
--- a/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.Designer.cs
+++ b/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.Designer.cs
@@ -9,21 +9,21 @@
namespace HotChocolate.Types.MongoDb.Resources {
using System;
-
-
+
+
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class MongoDbTypesResources {
-
+
private static System.Resources.ResourceManager resourceMan;
-
+
private static System.Globalization.CultureInfo resourceCulture;
-
+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal MongoDbTypesResources() {
}
-
+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager {
get {
@@ -34,7 +34,7 @@ internal static System.Resources.ResourceManager ResourceManager {
return resourceMan;
}
}
-
+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Globalization.CultureInfo Culture {
get {
@@ -44,11 +44,29 @@ internal static System.Globalization.CultureInfo Culture {
resourceCulture = value;
}
}
-
+
internal static string ObjectId_Type_Description {
get {
return ResourceManager.GetString("ObjectId_Type_Description", resourceCulture);
}
}
+
+ internal static string Bson_Type_Description {
+ get {
+ return ResourceManager.GetString("Bson_Type_Description", resourceCulture);
+ }
+ }
+
+ internal static string Bson_Type_CouldNotParseValue {
+ get {
+ return ResourceManager.GetString("Bson_Type_CouldNotParseValue", resourceCulture);
+ }
+ }
+
+ internal static string Bson_Type_CouldNotParseLiteral {
+ get {
+ return ResourceManager.GetString("Bson_Type_CouldNotParseLiteral", resourceCulture);
+ }
+ }
}
}
diff --git a/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.resx b/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.resx
index 42d3d2ab26a..aa769d8ee1b 100644
--- a/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.resx
+++ b/src/HotChocolate/MongoDb/src/Types/Resources/MongoDbTypesResources.resx
@@ -21,4 +21,13 @@
The ObjectId scalar type represents a 12 byte ObjectId, represented as UTF-8 character sequences.
+
+ BSON is a binary format in which zero or more ordered key/value pairs are stored as a single entity. The results are returned as JSON objects
+
+
+ Could not parse value {0}
+
+
+ Could not parse literal {0}
+
diff --git a/src/HotChocolate/MongoDb/src/Types/ThrowHelper.cs b/src/HotChocolate/MongoDb/src/Types/ThrowHelper.cs
new file mode 100644
index 00000000000..359e93054e8
--- /dev/null
+++ b/src/HotChocolate/MongoDb/src/Types/ThrowHelper.cs
@@ -0,0 +1,24 @@
+using HotChocolate.Language;
+using HotChocolate.Language.Utilities;
+using HotChocolate.Types.MongoDb.Resources;
+
+namespace HotChocolate.Types.MongoDb;
+
+internal static class ThrowHelper
+{
+ public static SerializationException Bson_CouldNotParseValue(
+ ScalarType type,
+ object? value) =>
+ new(
+ string.Format(
+ MongoDbTypesResources.Bson_Type_CouldNotParseValue,
+ value?.ToString() ?? "null"),
+ type);
+
+ public static SerializationException Bson_CouldNotParseLiteral(
+ ScalarType type,
+ IValueNode literal) =>
+ new(
+ string.Format(MongoDbTypesResources.Bson_Type_CouldNotParseLiteral, literal.Print()),
+ type);
+}
diff --git a/src/HotChocolate/MongoDb/test/Types.MongoDb/BsonTypeTests.cs b/src/HotChocolate/MongoDb/test/Types.MongoDb/BsonTypeTests.cs
new file mode 100644
index 00000000000..072add28df5
--- /dev/null
+++ b/src/HotChocolate/MongoDb/test/Types.MongoDb/BsonTypeTests.cs
@@ -0,0 +1,1265 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using HotChocolate.Execution;
+using HotChocolate.Language;
+using Microsoft.Extensions.DependencyInjection;
+using MongoDB.Bson;
+using Snapshooter;
+using Snapshooter.Xunit;
+using Xunit;
+using BsonType = HotChocolate.Types.MongoDb.BsonType;
+
+namespace HotChocolate.Types;
+
+public class BsonTypeTests
+{
+ [Fact]
+ public async Task Output_Should_BindAllRuntimeTypes()
+ {
+ // arrange
+ IRequestExecutor executor = await new ServiceCollection()
+ .AddGraphQL()
+ .AddBsonType()
+ .AddQueryType()
+ .BuildRequestExecutorAsync();
+
+ // act
+ // assert
+ executor.Schema.Print().MatchSnapshot();
+ }
+
+ [Fact]
+ public async Task Output_Should_MatchSnapshot_When_BsonDocument()
+ {
+ // arrange
+ IRequestExecutor executor = await new ServiceCollection()
+ .AddGraphQL()
+ .AddBsonType()
+ .AddQueryType()
+ .BuildRequestExecutorAsync();
+
+ // act
+ IExecutionResult result = await executor.ExecuteAsync("{ document }");
+
+ // assert
+ result.ToJson().MatchSnapshot();
+ }
+
+ [Fact]
+ public async Task Input_Should_MatchSnapshot_When_BsonDocument()
+ {
+ // arrange
+ object res = "INVALID";
+ IRequestExecutor executor = await new ServiceCollection()
+ .AddGraphQL()
+ .AddBsonType()
+ .AddQueryType(x => x.Name("Query")
+ .Field("in")
+ .Type()
+ .Argument("val", x => x.Type())
+ .Resolve(ctx =>
+ {
+ res = ctx.ArgumentValue