feat: defined logic for schema building
This commit is contained in:
parent
b7674e3278
commit
bb050e75d3
3 changed files with 202 additions and 72 deletions
2
.env
2
.env
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue