Implemented fragments shared between multiple queries by FabioStatespace · Pull Request #18 · statespacelabs/SimpleGraphQL-For-Unity · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions Editor/SimpleGraphQL/GraphQLFragmentImporter.cs
3 changes: 3 additions & 0 deletions Editor/SimpleGraphQL/GraphQLFragmentImporter.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Editor/SimpleGraphQL/GraphQLImporterV1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,15 @@ public override void OnImportAsset(AssetImportContext ctx)
Debug.LogWarning("Unable to convert operation type in " + ctx.assetPath);
}

var fragments = operation.Descendants().Where(node => node is GraphQLFragmentSpread).Select(node => ((GraphQLFragmentSpread)node).Name.Value).ToArray();

queryFile.Queries.Add(new Query
{
FileName = fileName,
OperationName = operation.Name?.Value,
OperationType = operationType,
Source = contents
Source = contents,
Fragments = fragments
});
}
}
Expand Down
40 changes: 38 additions & 2 deletions Plugins/SimpleGraphQL/GraphQLParser/AST/ASTNode.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace SimpleGraphQL.GraphQLParser.AST
using System.Collections.Generic;
using System.Linq;

namespace SimpleGraphQL.GraphQLParser.AST
{
public abstract class ASTNode
{
Expand All @@ -7,5 +10,38 @@ public abstract class ASTNode
public GraphQLLocation Location { get; set; }

public GraphQLComment Comment { get; set; }

}

public static class ASTNodeExtensions
{
public static IEnumerable<ASTNode> Descendants(this ASTNode root)
{
var nodes = new Stack<ASTNode>(new[] {root});
while (nodes.Any())
{
ASTNode node = nodes.Pop();
yield return node;

GraphQLSelectionSet selectionSet = null;

if (node is GraphQLFieldSelection fieldSelection)
{
selectionSet = fieldSelection.SelectionSet;
}

if (node is GraphQLOperationDefinition operationDefinition)
{
selectionSet = operationDefinition.SelectionSet;
}

if(selectionSet != null && selectionSet.Selections != null)
{
foreach (var n in selectionSet.Selections)
nodes.Push(n);
}
}
}

}
}
}
52 changes: 52 additions & 0 deletions Runtime/SimpleGraphQL/Fragment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using JetBrains.Annotations;
using UnityEngine;

namespace SimpleGraphQL
{
[PublicAPI]
[Serializable]
public class Fragment
{
/// <summary>
/// The name of the fragment.
/// </summary>
[CanBeNull]
public string Name;

/// <summary>
/// The type the fragment is selecting from.
/// </summary>
public string TypeCondition;

/// <summary>
/// The actual fragment itself.
/// </summary>
[TextArea]
public string Source;

public override string ToString()
{
return $"fragment {Name} on {TypeCondition}";
}

protected bool Equals(Fragment other)
{
return Name == other.Name;
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Fragment)obj);
}

public override int GetHashCode()
{
return (Name != null ? Name.GetHashCode() : 0);
}
}

}
3 changes: 3 additions & 0 deletions Runtime/SimpleGraphQL/Fragment.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 25 additions & 2 deletions Runtime/SimpleGraphQL/GraphQLClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class GraphQLClient
{
public readonly List<Query> SearchableQueries;
public readonly Dictionary<string, string> CustomHeaders;
public readonly Dictionary<string, Fragment> Fragments;

public string Endpoint;
public string AuthScheme;
Expand All @@ -24,13 +25,14 @@ public GraphQLClient(
string endpoint,
IEnumerable<Query> queries = null,
Dictionary<string, string> headers = null,
string authScheme = null
)
string authScheme = null,
IEnumerable<Fragment> fragments = null)
{
Endpoint = endpoint;
AuthScheme = authScheme;
SearchableQueries = queries?.ToList();
CustomHeaders = headers;
Fragments = fragments?.ToDictionary(fragment => fragment.Name);
}

public GraphQLClient(GraphQLConfig config)
Expand All @@ -39,6 +41,7 @@ public GraphQLClient(GraphQLConfig config)
SearchableQueries = config.Files.SelectMany(x => x.Queries).ToList();
CustomHeaders = config.CustomHeaders.ToDictionary(header => header.Key, header => header.Value);
AuthScheme = config.AuthScheme;
Fragments = config.Fragments.ToDictionary(file => file.Fragment.Name, file => file.Fragment);
}

/// <summary>
Expand Down Expand Up @@ -342,5 +345,25 @@ public List<Query> FindQueriesByOperation(string operation)
{
return SearchableQueries?.FindAll(x => x.OperationName == operation);
}

public List<Fragment> FindFragments(IEnumerable<string> fragmentNames)
{
List<Fragment> fragments = new();

if (fragmentNames == null)
{
return fragments;
}

foreach (var fragmentName in fragmentNames)
{
if (Fragments.TryGetValue(fragmentName, out var fragment))
{
fragments.Add(fragment);
}
}

return fragments;
}
}
}
3 changes: 3 additions & 0 deletions Runtime/SimpleGraphQL/GraphQLConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class GraphQLConfig : ScriptableObject
[Header(".graphql Files")]
public List<GraphQLFile> Files;

[Header("Fragment files")]
public List<GraphQLFragmentFile> Fragments;

/// <summary>
/// Set the auth scheme to be used here if you need authentication.
/// You can also use CustomHeaders to pass in authentication if needed, but this is inherently less secure.
Expand Down
10 changes: 10 additions & 0 deletions Runtime/SimpleGraphQL/GraphQLFragmentFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Collections.Generic;
using UnityEngine;

namespace SimpleGraphQL
{
public class GraphQLFragmentFile : ScriptableObject
{
public Fragment Fragment;
}
}
3 changes: 3 additions & 0 deletions Runtime/SimpleGraphQL/GraphQLFragmentFile.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 23 additions & 6 deletions Runtime/SimpleGraphQL/Query.cs