Type::boolean(), Model::TYPE_STRING => Type::string(), Model::TYPE_INTEGER => Type::int(), Model::TYPE_FLOAT => Type::float(), // Outliers Model::TYPE_JSON => Type::string(), Response::MODEL_ANY => Type::string(), ]; function createTypeMapping(Model $model, Response $response) { global $typeMapping; // If map already contains this complex type, then simply return if (isset($typeMapping[$model->getType()])) return; $rules = $model->getRules(); $name = $model->getType(); $fields = []; foreach ($rules as $key => $props) { // Replace this with php regex $key = str_replace('$', '', $key); if (isset( $typeMapping[$props['type']])) { $type = $typeMapping[$props['type']]; } else { try { $complexModel = $response->getModel($props['type']); createTypeMapping($complexModel, $response); $type = $typeMapping[$props['type']]; } catch (Exception $e) { var_dump("Could Not find model for : {$props['type']}"); } } if ($props['array']) { $type = Type::listOf($type); } $fields[$key] = [ 'type' => $type, 'description' => $props['description'], ]; } $objectType = [ 'name' => $name, 'fields' => $fields ]; $typeMapping[$name] = new ObjectType($objectType); } function getArgType($validator, bool $required, $utopia, $injections) { $validator = (\is_callable($validator)) ? call_user_func_array($validator, $utopia->getResources($injections)) : $validator; $type = []; switch ((!empty($validator)) ? \get_class($validator) : '') { case 'Utopia\Validator\Text': $type = Type::string(); break; case 'Utopia\Validator\Boolean': $type = Type::boolean(); break; case 'Appwrite\Database\Validator\UID': $type = Type::string(); break; case 'Utopia\Validator\Email': $type = Type::string(); break; case 'Utopia\Validator\URL': $type = Type::string(); break; case 'Utopia\Validator\JSON': case 'Utopia\Validator\Mock': case 'Utopia\Validator\Assoc': $type = Type::string(); break; case 'Appwrite\Storage\Validator\File': $type = Type::string(); case 'Utopia\Validator\ArrayList': $type = Type::listOf(Type::string()); break; case 'Appwrite\Auth\Validator\Password': $type = Type::string(); break; case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */ $type = Type::int(); break; case 'Utopia\Validator\Numeric': $type = Type::int(); break; case 'Utopia\Validator\Length': $type = Type::string(); break; case 'Utopia\Validator\Host': $type = Type::string(); break; case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */ $type = Type::string(); break; default: $type = Type::string(); break; } if ($required) { $type = Type::nonNull($type); } return $type; } function getArgs(array $params, $utopia) { $args = []; foreach ($params as $key => $value) { $args[$key] = [ 'type' => getArgType($value['validator'],!$value['optional'], $utopia, $value['injections']), 'description' => $value['description'], 'defaultValue' => $value['default'] ]; } return $args; } function buildSchema($utopia, $response) { $start = microtime(true); global $typeMapping; $queryFields = []; $mutationFields = []; foreach($utopia->getRoutes() as $method => $routes ){ foreach($routes as $route) { $namespace = $route->getLabel('sdk.namespace', ''); if ($namespace == 'users') { $methodName = $namespace.'_'.$route->getLabel('sdk.method', ''); $responseModelName = $route->getLabel('sdk.response.model', ""); var_dump("******************************************"); var_dump("Processing route : ${method} : {$route->getURL()}"); var_dump("Model Name : ${responseModelName}"); if ( $responseModelName !== Response::MODEL_NONE && $responseModelName !== Response::MODEL_ANY ) { $responseModel = $response->getModel($responseModelName); createTypeMapping($responseModel, $response); $type = $typeMapping[$responseModel->getType()]; var_dump("Type Created : ${type}"); $args = getArgs($route->getParams(), $utopia); var_dump("Args Generated : ${args}"); $field = [ 'type' => $type, 'description' => $route->getDesc(), 'args' => $args, 'resolve' => function ($args) use (&$utopia, $route, $response) { var_dump("************* REACHED RESOLVE *****************"); var_dump($route); $utopia->execute($route, $args); var_dump("********************** ARGS *******************"); var_dump($args); var_dump("**************** OUTPUT ************"); var_dump($response->getPayload()); return $response->getPayload(); } ]; if ($method == 'GET') { $queryFields[$methodName] = $field; } else if ($method == 'POST' || $method == 'PUT' || $method == 'PATCH' || $method == 'DELETE') { $mutationFields[$methodName] = $field; } var_dump("Processed route : ${method} : {$route->getURL()}"); } else { var_dump("Skipping route : {$route->getURL()}"); } } } } ksort($queryFields); ksort($mutationFields); $queryType = new ObjectType([ 'name' => 'Query', 'description' => 'The root of all your queries', 'fields' => $queryFields ]); $mutationType = new ObjectType([ 'name' => 'Mutation', 'description' => 'The root of all your mutations', 'fields' => $mutationFields ]); $schema = new Schema([ 'query' => $queryType, 'mutation' => $mutationType ]); $time_elapsed_secs = microtime(true) - $start; var_dump("Time Taken To Build Schema : ${time_elapsed_secs}s"); return $schema; } App::post('/v1/graphql') ->desc('GraphQL Endpoint') ->groups(['api', 'graphql']) ->label('scope', 'public') ->inject('request') ->inject('response') ->inject('utopia') ->action(function ($request, $response, $utopia) { // Generate the Schema of the server on startup. // Use the routes from utopia and get the params then construct the queries and mutations. $schema = buildSchema($utopia, $response); $query = $request->getPayload('query', ''); $variables = $request->getPayload('variables', null); $response->setContentType(Response::CONTENT_TYPE_NULL); try { $rootValue = []; $result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variables); $output = $result->toArray(); var_dump("********** OUTPUT *********"); var_dump($output); } catch (\Exception $error) { $output = [ 'errors' => [ [ 'message' => $error->getMessage().'xxx', 'code' => $error->getCode(), 'file' => $error->getFile(), 'line' => $error->getLine(), 'trace' => $error->getTrace(), ] ] ]; } $response->json($output); echo "\n"; //TODO REMOVE THIS } );