Skip to content

Commit

Permalink
array resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
burner committed Aug 4, 2023
1 parent c027316 commit 878b3d5
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 8 deletions.
1 change: 1 addition & 0 deletions dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"nullablestore": ">=2.1.0"
},
"dflags": [ "-d"],
"dflags-ldc": ["-d", "-ftime-trace", "-ftime-trace-file=$PACKAGE_DIR/trace.json", "-wi"],
"description": "A library to handle the GraphQL Protocol",
"copyright": "Copyright © 2019, Robert burner Schadek",
"license": "LGPL3"
Expand Down
40 changes: 40 additions & 0 deletions source/graphql/graphql.d
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,18 @@ private struct ExecutionContext {
}
}

struct ParentArgs {
Json parent;
Json args;
}

class GraphQLD(T, QContext = DefaultContext) {
alias Con = QContext;
alias QueryResolver = Json delegate(string name, Json parent,
Json args, ref Con context) @safe;
alias QueryArrayResolver = Json delegate(string name, ParentArgs parentArgs
, Selections selections, ref Con context) @safe;

alias DefaultQueryResolver = Json delegate(string name, Json parent,
Json args, ref Con context, ref ExecutionContext ec) @safe;

Expand All @@ -74,6 +82,7 @@ class GraphQLD(T, QContext = DefaultContext) {

// [Type][field]
QueryResolver[string][string] resolver;
QueryArrayResolver[string][string] arrayResolver;
DefaultQueryResolver defaultResolver;

this(GQLDOptions options = GQLDOptions.init) {
Expand Down Expand Up @@ -137,6 +146,17 @@ class GraphQLD(T, QContext = DefaultContext) {
}
}

void setArrayResolver(string first, string second
, QueryArrayResolver resolver)
{
if(first !in this.arrayResolver) {
this.arrayResolver[first] = QueryArrayResolver[string].init;
}
enforce(second !in this.arrayResolver[first], format(
"'%s'.'%s' is already registered", first, second));
this.arrayResolver[first][second] = resolver;
}

Json resolve(string type, string field, Json parent, Json args,
ref Con context, ref ExecutionContext ec)
{
Expand Down Expand Up @@ -441,8 +461,28 @@ class GraphQLD(T, QContext = DefaultContext) {
);
enforce("data" in objectValue, "Excepted object got " ~ objectValue.toString());
GQLDType elemType = objectType.elementType;
GQLDType unPacked = unpack2(elemType);

this.executationTraceLog.logf("elemType %s", elemType);
Json ret = returnTemplate();
QueryArrayResolver[string]* arrayTypeResolverArray = unPacked.name in this.arrayResolver;
GQLDMap elemTypeMap = toMap(unPacked);
QueryArrayResolver* arrayTypeResolver = elemTypeMap is null
? null
: elemTypeMap.name in (*arrayTypeResolverArray);

writefln("Array Resolver %s %s %s %s", unPacked.name
, elemTypeMap is null
? ""
: elemTypeMap.name
, arrayTypeResolver !is null
, ss.sel);
if(arrayTypeResolver !is null) {
(*arrayTypeResolver)(elemTypeMap.name
, ParentArgs(objectValue, variables)
, ss.sel, context);
}

ret["data"] = Json.emptyArray();
if(this.options.asyncList == AsyncList.yes) {
Task[] tasks;
Expand Down
2 changes: 1 addition & 1 deletion source/graphql/testschema.d
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct Query {
Starship[] starships(float overSize = 100.0);
Starship[] shipsselection(long[] ids);
Nullable!Character character(long id);
Character[] character(Series series);
Character[] characters(Series series);
Humanoid[] humanoids();
Android[] androids();
Android[] resolverWillThrow();
Expand Down
5 changes: 3 additions & 2 deletions test/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ type mutationType {
}
type queryType {
shipsselection(ids: [Int!]!): [Starship!]!
currentTime: DateTime!
characters(series: Series!): [Character!]!
starships(overSize: Float!): [Starship!]!
captain(series: Series!): Character!
humanoids: [Humanoid!]!
name: String!
currentTime: DateTime!
starship(id: Int!): Starship
starshipSimple2(id: Int!): StarshipSimple2
name: String!
androids: [Android!]!
resolverWillThrow: [Android!]!
numberBetween(searchInput: InputIn!): Starship!
Expand Down
63 changes: 59 additions & 4 deletions test/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ void main() {
version(LDC) {
graphqld.defaultResolverLog.logLevel = std.experimental.logger.LogLevel.off;
graphqld.resolverLog.logLevel = std.experimental.logger.LogLevel.off;
//graphqld.executationTraceLog = new std.experimental.logger.FileLogger("exec.log");
graphqld.executationTraceLog.logLevel = std.experimental.logger.LogLevel.off;
graphqld.executationTraceLog = new std.experimental.logger.FileLogger("exec.log");
graphqld.executationTraceLog.logLevel = std.experimental.logger.LogLevel.trace;
} else {
graphqld.defaultResolverLog.logLevel = std.logger.LogLevel.off;
graphqld.resolverLog.logLevel = std.logger.LogLevel.off;
//graphqld.executationTraceLog = new std.experimental.logger.FileLogger("exec.log");
graphqld.executationTraceLog.logLevel = std.logger.LogLevel.off;
graphqld.executationTraceLog = new std.experimental.logger.FileLogger("exec.log");
graphqld.executationTraceLog.logLevel = std.logger.LogLevel.trace;
}

testSchemaDump("schema.gql", schemaToString(graphqld));
Expand Down Expand Up @@ -184,6 +184,32 @@ void main() {
}
);

graphqld.setResolver("queryType", "character"
, delegate(string name, Json parent, Json args,
ref CustomContext con) @safe
{
Json ret = Json.emptyObject();
bool isObject = cast(bool)(args.type == Json.Type.object);
bool hasId = isObject
? cast(bool)("id" in args)
: false;
if(hasId) {
long id = args["id"].get!long();
foreach(ref it; database.chars) {
if(it.id == id) {
return characterToJson(it);
}
}
ret["errors"] = "No character by id %d found in args"
.format(id);
return ret;
} else {
ret["errors"] = "No id found in args";
return ret;
}
}
);

graphqld.setResolver("queryType", "starship",
delegate(string name, Json parent, Json args,
ref CustomContext con) @safe
Expand Down Expand Up @@ -334,6 +360,35 @@ void main() {
}
);

graphqld.setResolver("Character", "commands",
delegate(string name, Json parent, Json args
, ref CustomContext) @trusted
{
Json data = Json.emptyArray();
if("commandsIds" in parent) {
foreach(it; parent["commandsIds"]) {
auto c = database.chars.filter!(jt => jt.id == it);
if(!c.empty) {
data ~= characterToJson(c.front);
}
}
}
Json ret = Json.emptyObject();
ret["data"] = data;
return ret;
}
);

graphqld.setArrayResolver("Character", "commands",
delegate(string name, ParentArgs parentArgs
, Selections selection, ref CustomContext context) @trusted
{
writefln("HEERRRRRRR %s %s %s", name, parentArgs, selection);
Json ret = Json.emptyObject();
return ret;
}
);

auto settings = new HTTPServerSettings;
settings.port = 8080;
settings.bindAddresses = ["::1", "127.0.0.1"];
Expand Down
3 changes: 2 additions & 1 deletion test/source/testdata.d
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ Json characterToJson(Character c) {

if(Humanoid h = cast(Humanoid)c) {
ret["data"]["species"] = h.species;
ret["data"]["__typename"] = "Humanoid";
//ret["data"]["__typename"] = "Humanoid"; TODO reverse hack
ret["data"]["__typename"] = "Character";
ret["data"]["dateOfBirth"] = Json(h.dateOfBirth.toISOExtString());
}

Expand Down

0 comments on commit 878b3d5

Please sign in to comment.