1
0
Fork 0
mirror of synced 2024-06-27 18:50:47 +12:00

feat: defined logic for schema building

This commit is contained in:
Christy Jacob 2021-02-26 02:13:21 +05:30
parent b7674e3278
commit bb050e75d3
3 changed files with 202 additions and 72 deletions

2
.env
View file

@ -15,7 +15,7 @@ _APP_DB_PORT=3306
_APP_DB_SCHEMA=appwrite
_APP_DB_USER=user
_APP_DB_PASS=password
_APP_STORAGE_ANTIVIRUS=enabled
_APP_STORAGE_ANTIVIRUS=disabled
_APP_STORAGE_ANTIVIRUS_HOST=clamav
_APP_STORAGE_ANTIVIRUS_PORT=3310
_APP_INFLUXDB_HOST=influxdb

View file

@ -4,7 +4,11 @@ use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use GraphQL\Type\Definition\NonNull;
use Utopia\App;
use Utopia\Validator;
/**
* TODO:
@ -34,83 +38,210 @@ use Utopia\App;
* - Objects
*/
global $typeMapping;
$typeMapping = [
Model::TYPE_BOOLEAN => 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 $validator, bool $required) {
$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 = 'string';
break;
}
if ($required) {
$type = Type::nonNull($type);
}
return $type;
}
function getArgs(array $params) {
$args = [];
foreach ($params as $key => $value) {
var_dump("Key : ${key}");
var_dump($value);
$args[$key] = [
'type' => getArgType($value['validator'],!$value['optional']),
'description' => $value['description'],
'defaultValue' => $value['default']
];
}
return $args;
}
function buildSchema($utopia, $response) {
$start = microtime(true);
global $typeMapping;
$fields = [];
foreach($utopia->getRoutes() as $method => $routes ){
if ($method == "GET") {
foreach($routes as $route) {
$namespace = $route->getLabel('sdk.namespace', '');
if( true ) {
$methodName = $namespace.'_'.$route->getLabel('sdk.method', '');
$responseModelName = $route->getLabel('sdk.response.model', Response::MODEL_NONE);
var_dump("******************************************");
var_dump("Model Name : ${responseModelName}");
if ( $responseModelName !== Response::MODEL_NONE && $responseModelName !== Response::MODEL_ANY ) {
$responseModel = $response->getModel($responseModelName);
createTypeMapping($responseModel, $response);
$fields[$methodName] = [
'type' => $typeMapping[$responseModel->getType()],
'description' => $route->getDesc(),
'args' => getArgs($route->getParams()),
];
// print_r($fields[$methodName]);
var_dump("Processed route : {$route->getURL()}");
} else {
var_dump("Skipping route : {$route->getURL()}");
}
}
}
}
}
ksort($fields);
$queryType = new ObjectType([
'name' => 'Query',
'description' => 'The root of all your queries',
'fields' => $fields
]);
$schema = new Schema([
'query' => $queryType
]);
$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')
->action(
function () use ($request, $response, $utopia) {
foreach ($utopia->getRoutes() as $method => $routes) {
var_dump($method);
foreach ($routes as $key => $route) {
var_dump($key);
}
}
$userType = new ObjectType([
'name' => 'User',
'fields' => [
'name' => [
'type' => Type::string(),
],
],
]);
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'echo' => [
'type' => Type::string(),
'args' => [
'message' => ['type' => Type::string()],
],
'resolve' => function ($rootValue, $args) {
return $rootValue['prefix'] . $args['message'];
}
],
'users' => [
'type' => Type::listOf($userType),
//'type' => $userType,
'args' => [
'message' => ['type' => Type::string()],
],
'resolve' => function ($rootValue, $args) {
return ['name' => 'Eldad Fux'];
return [
['name' => 'Eldad Fux'],
['name' => 'Sharon Kapon'],
];
}
],
],
]);
$mutationType = new ObjectType([
'name' => 'Mutation',
'fields' => [
'sum' => [
'type' => Type::int(),
'args' => [
'x' => ['type' => Type::int()],
'y' => ['type' => Type::int()],
],
'resolve' => function ($calc, $args) {
return $args['x'] + $args['y'];
},
],
],
]);
$schema = new Schema([
'query' => $queryType,
'mutation' => $mutationType,
]);
->inject('request')
->inject('response')
->inject('utopia')
->inject('schema')
->action(function ($request, $response, $utopia, $schema) {
// 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);
try {
$rootValue = [];
$result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variables);
@ -128,7 +259,6 @@ App::post('/v1/graphql')
]
];
}
$response->json($output);
echo "\n"; //TODO REMOVE THIS
}

View file

@ -495,7 +495,7 @@ services:
ports:
- '9505:4000'
environment:
- API_URL=http://192.168.1.102/v1/graphql
- API_URL=http://localhost/v1/graphql
image: npalm/graphiql
networks: