Handle response model union type rules
This commit is contained in:
parent
1fbcedec42
commit
6ac4d4f490
5 changed files with 43 additions and 124 deletions
12
composer.lock
generated
12
composer.lock
generated
|
@ -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": [],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue