1
0
Fork 0
mirror of synced 2024-09-29 17:01:37 +13:00

Handle response model union type rules

This commit is contained in:
Jake Barnby 2022-09-30 19:59:20 +13:00
parent 1fbcedec42
commit 6ac4d4f490
No known key found for this signature in database
GPG key ID: C437A8CC85B96E9C
5 changed files with 43 additions and 124 deletions

12
composer.lock generated
View file

@ -5349,16 +5349,16 @@
},
{
"name": "twig/twig",
"version": "v3.4.2",
"version": "v3.4.3",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077"
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077",
"reference": "e07cdd3d430cd7e453c31b36eb5ad6c0c5e43077",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
"shasum": ""
},
"require": {
@ -5409,7 +5409,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.4.2"
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
},
"funding": [
{
@ -5421,7 +5421,7 @@
"type": "tidelift"
}
],
"time": "2022-08-12T06:47:24+00:00"
"time": "2022-09-28T08:42:51+00:00"
}
],
"aliases": [],

View file

@ -846,7 +846,7 @@ services:
graphql-explorer:
container_name: appwrite-graphql-explorer
image: appwrite/altair:0.1.0
image: appwrite/altair:0.2.0
restart: unless-stopped
networks:
- appwrite

View file

@ -209,7 +209,11 @@ class TypeMapper
foreach ($model->getRules() as $key => $rule) {
$escapedKey = str_replace('$', '_', $key);
if (\is_array($rule['type'])) {
$type = self::getUnionType($escapedKey, $rule);
} else {
$type = self::getObjectType($rule);
}
if ($rule['array']) {
$type = Type::listOf($type);
@ -372,4 +376,27 @@ class TypeMapper
return self::fromResponseModel(\ucfirst($complexModel->getType()));
}
private static function getUnionType(string $name, array $rule): Type
{
$unionName = \ucfirst($name);
if (TypeRegistry::has($unionName)) {
return TypeRegistry::get($unionName);
}
$types = [];
foreach ($rule['type'] as $type) {
$types[] = self::fromResponseModel(\ucfirst($type));
}
$unionType = new UnionType([
'name' => $unionName,
'types' => $types,
'resolveType' => static fn($object) => $object['type'],
]);
TypeRegistry::set($unionName, $unionType);
return $unionType;
}
}

View file

@ -8,54 +8,13 @@ use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use Utopia\CLI\Console;
use Utopia\Database\Database;
class TypeRegistry
{
private static array $typeMapping = [];
private static array $defaultDocumentArgs = [];
private static array $models = [];
/**
* Initialize the type registry for the given set of models.
*
* @param array<Model> $models
*/
public static function init(array $models): void
{
self::$typeMapping = [
Model::TYPE_BOOLEAN => Type::boolean(),
Model::TYPE_STRING => Type::string(),
Model::TYPE_INTEGER => Type::int(),
Model::TYPE_FLOAT => Type::float(),
Model::TYPE_DATETIME => Type::string(),
Model::TYPE_JSON => static::json(),
Response::MODEL_NONE => static::json(),
Response::MODEL_ANY => static::json(),
];
self::$defaultDocumentArgs = [
'id' => [
'id' => [
'type' => Type::nonNull(Type::string()),
],
],
'list' => [
'queries' => [
'type' => Type::listOf(Type::nonNull(Type::string())),
'defaultValue' => [],
],
],
'mutate' => [
'permissions' => [
'type' => Type::listOf(Type::nonNull(Type::string())),
'defaultValue' => [],
]
],
];
self::$models = $models;
}
private static array $register = [];
/**
* Check if a type exists in the registry.
@ -65,70 +24,18 @@ class TypeRegistry
*/
public static function has(string $type): bool
{
return isset(self::$typeMapping[$type]);
return isset(self::$register[$type]);
}
/**
* Get a type from the registry, creating it if it does not already exist.
* Get a type from the registry.
*
* @param string $name
* @param string $type
* @return Type
*/
public static function get(string $name): Type
public static function get(string $type): Type
{
if (self::has($name)) {
return self::$typeMapping[$name];
}
$fields = [];
$model = self::$models[\lcfirst($name)];
if ($model->isAny()) {
$fields['data'] = [
'type' => Type::string(),
'description' => 'Additional data',
'resolve' => static fn($object, $args, $context, $info) => \json_encode($object, JSON_FORCE_OBJECT),
];
}
foreach ($model->getRules() as $key => $props) {
$escapedKey = str_replace('$', '_', $key);
$types = \is_array($props['type'])
? $props['type']
: [$props['type']];
foreach ($types as $type) {
if (self::has($type)) {
$type = self::$typeMapping[$type];
} else {
try {
$complexModel = self::$models[$type];
$type = self::get($complexModel->getType());
} catch (\Exception) {
Console::error('Could not find model for ' . $type);
}
}
if ($props['array']) {
$type = Type::listOf($type);
}
$fields[$escapedKey] = [
'type' => $type,
'description' => $props['description'],
];
}
}
$objectType = [
'name' => $name,
'fields' => $fields
];
self::set($name, new ObjectType($objectType));
return self::$typeMapping[$name];
return self::$register[$type];
}
/**
@ -139,21 +46,6 @@ class TypeRegistry
*/
public static function set(string $type, Type $typeObject): void
{
self::$typeMapping[$type] = $typeObject;
}
/**
* Get the registered default arguments for a given key.
*
* @param string $key
* @return array
*/
public static function argumentsFor(string $key): array
{
if (isset(self::$defaultDocumentArgs[$key])) {
return self::$defaultDocumentArgs[$key];
}
return [];
}
self::$register[$type] = $typeObject;
}
}

View file

@ -27,6 +27,6 @@ class BuilderTest extends TestCase
public function testCreateTypeMapping()
{
$model = $this->response->getModel(Response::MODEL_COLLECTION);
$typeMapping = TypeRegistry::get($model->getType());
$typeMapping = TypeRegistry::fromModel($model->getType());
}
}