1 module graphql.reflection; 2 import graphql.traits; 3 import std.traits; 4 import std.meta; 5 import vibe.data.json; 6 7 @safe: 8 9 package struct TypeWithStrippedName { 10 Json typeJson; 11 string name; 12 bool canonical; 13 } 14 15 package struct SchemaReflection(Schema) { 16 private { 17 static SchemaReflection _instance; 18 bool initialized; 19 } 20 21 static SchemaReflection *instance() @safe { 22 _instance.initialize(); 23 return &_instance; 24 } 25 26 string[TypeInfo] classes; 27 string[][TypeInfo] derivatives; 28 string[][string] bases; 29 30 TypeWithStrippedName[string] jsonTypes; 31 32 private: 33 34 void initialize() @safe { 35 if(initialized) { 36 return; 37 } 38 initialized = true; 39 40 execForAllTypes!(Schema, builder)(this); 41 execForAllTypes!(Schema, builderPhase2)(this); 42 } 43 } 44 45 private void builder(T,Schema)(ref SchemaReflection!Schema ths) { 46 static if(is(T == class)) { 47 ths.classes[typeid(T)] = T.stringof; 48 foreach(B; AliasSeq!(T, TransitiveBaseTypeTuple!T)) { 49 static if(!is(B == Object)) { 50 ths.derivatives.require(typeid(B), null) ~= T.stringof; 51 ths.bases.require(T.stringof, null) ~= B.stringof; 52 } 53 } 54 } else static if(is(T == interface)) { 55 // go through all base types, and set up the derivation lines 56 foreach(B; AliasSeq!(T, InterfacesTuple!T)) { 57 ths.derivatives.require(typeid(B), null) ~= T.stringof; 58 ths.bases.require(T.stringof, null) ~= B.stringof; 59 } 60 } else { 61 // all other types have derivatives and bases of themselves 62 ths.derivatives.require(typeid(T), null) ~= T.stringof; 63 ths.bases.require(T.stringof, null) ~= T.stringof; 64 } 65 } 66 67 private void builderPhase2(T,Schema)(ref SchemaReflection!Schema ths) { 68 import graphql.schema.typeconversions : typeToTypeName, typeToJsonImpl; 69 // build the second parts which need the first parts 70 alias stripped = stripArrayAndNullable!T; 71 ths.jsonTypes[typeToTypeName!T] = 72 TypeWithStrippedName(typeToJsonImpl!(stripped, Schema, T)(), 73 stripped.stringof, 74 is(stripArrayAndNullable!T == T)); 75 }