1
0
Fork 0
mirror of synced 2024-06-14 08:44:49 +12:00

Fix collection type arg and type setting

This commit is contained in:
Jake Barnby 2022-04-08 02:02:48 +12:00
parent b1521a2b33
commit 40b04a3721
No known key found for this signature in database
GPG key ID: A4674EBC0E404657
4 changed files with 230 additions and 233 deletions

View file

@ -309,7 +309,7 @@ Things to remember when releasing SDKs
Appwrite uses [yasd](https://github.com/swoole/yasd) debugger, which can be made available during build of Appwrite. You can connect to the debugger using VS Code [PHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug) extension or if you are in PHP Storm you don't need any plugin. Below are the settings required for remote debugger connection.
First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger wont connect. And you also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** file and name it **dev/yasd_init.php** and there change the IP address to your development machine's IP. Without the proper IP address debugger will not connect. You will also need to set **DEBUG** build arg in **appwrite** service in **docker-compose.yml** file.
### VS Code Launch Configuration
@ -321,13 +321,13 @@ First, you need to create an init file. Duplicate **dev/yasd_init.php.stub** fil
"port": 9005,
"pathMappings": {
"/usr/src/code": "${workspaceRoot}"
},
}
}
```
### PHPStorm Setup
In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, there under **Xdebug** set the debug port to **9005** and enable **can accept external connections** checkbox.
In settings, go to **Languages & Frameworks** > **PHP** > **Debug**, there under **Xdebug** set the debug port to **9005** and enable the **can accept external connection** checkbox.
## Tests
@ -349,7 +349,7 @@ To run end-2-end tests use:
docker-compose exec appwrite test /usr/src/code/tests/e2e
```
To run end-2-end tests for a spcific service use:
To run end-2-end tests for a specific service use:
```bash
docker-compose exec appwrite test /usr/src/code/tests/e2e/Services/[ServiceName]
@ -406,9 +406,11 @@ docker-compose exec appwrite /usr/src/code/vendor/bin/psalm
From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials:
* [Adding Support for a New OAuth2 Provider](./docs/tutorials/add-oauth2-provider.md)
* [Appwrite Environment Variables](./docs/tutorials/environment-variables.md)
* [Running in Production](./docs/tutorials/running-in-production.md)
* [Appwrite Environment Variables](./docs/tutorials/add-environment-variable.md)
* [Adding Support for a New Runtime](./docs/tutorials/add-runtime.md)
* [Adding Storage Adapter](./docs/tutorials/add-storage-adapter.md)
* [Adding Translations](./docs/tutorials/add-translations.md)
* [Multi-Architecture Support](./docs/tutorials/multi-architecture-support.md)
## Other Ways to Help
@ -416,7 +418,7 @@ Pull requests are great, but there are many other areas where you can help Appwr
### Blogging & Speaking
Blogging, speaking about, or creating tutorials about one of Appwrites many features. Mention [@appwrite](https://twitter.com/appwrite) on Twitter and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub.
Blogging, speaking about, or creating tutorials about one of Appwrites many features. Mention [@appwrite](https://twitter.com/appwrite) on Twitter and/or [email team@appwrite.io](mailto:team@appwrite.io), so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub.
### Presenting at Meetups
@ -437,4 +439,3 @@ Submitting documentation updates, enhancements, designs, or bug fixes. Spelling
### Helping Someone
Searching for Appwrite on Discord, GitHub, or StackOverflow and helping someone else who needs help. You can also help by teaching others how to contribute to Appwrite's repo!

View file

@ -65,7 +65,7 @@ App::post('/v1/graphql')
$apiSchema,
$register,
$dbForProject
);;
);
$promise = GraphQL::promiseToExecute(
$promiseAdapter,
@ -76,18 +76,18 @@ App::post('/v1/graphql')
validationRules: $validations
);
// Blocking wait while queries resolve asynchronously.
// Blocking wait while queries resolve asynchronously
$wg = new WaitGroup();
$wg->add();
$promise->then(
function ($result) use ($response, $debugFlags, $wg) {
$response->json(['data' => $result->toArray($debugFlags)]);
$response->json($result->toArray($debugFlags));
$wg->done();
},
function ($error) use ($response, $wg) {
$response->json(['errors' => [\json_encode($error)]]);
$response->text(\json_encode(['errors' => [\json_encode($error)]]));
$wg->done();
}
);
$wg->wait();
$wg->wait(App::getEnv('_APP_GRAPHQL_REQUEST_TIMEOUT', 30));
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -3,6 +3,7 @@
namespace Appwrite\GraphQL;
use Appwrite\GraphQL\Types\JsonType;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use GraphQL\Error\Error;
@ -14,7 +15,6 @@ use Utopia\App;
use Utopia\CLI\Console;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Registry\Registry;
@ -95,28 +95,34 @@ class Builder
foreach ($rules as $key => $props) {
$escapedKey = str_replace('$', '_', $key);
if (isset(self::$typeMapping[$props['type']])) {
$type = self::$typeMapping[$props['type']];
} else {
try {
$complexModel = $response->getModel($props['type']);
$type = self::getTypeMapping($complexModel, $response);
} catch (\Exception $e) {
Console::error("Could Not find model for : {$props['type']}");
}
}
$types = \is_array($props['type'])
? $props['type']
: [$props['type']];
if ($props['array']) {
$type = Type::listOf($type);
}
$fields[$escapedKey] = [
'type' => $type,
'description' => $props['description'],
'resolve' => function ($object, $args, $context, $info) use ($key) {
return $object[$key];
foreach ($types as $type) {
if (isset(self::$typeMapping[$type])) {
$type = self::$typeMapping[$type];
} else {
try {
$complexModel = $response->getModel($type);
$type = self::getTypeMapping($complexModel, $response);
} catch (\Exception $e) {
Console::error("Could not find model for : {$type}");
}
}
];
if ($props['array']) {
$type = Type::listOf($type);
}
$fields[$escapedKey] = [
'type' => $type,
'description' => $props['description'],
'resolve' => function ($object, $args, $context, $info) use ($key) {
return $object[$key];
}
];
}
}
$objectType = [
'name' => $name,
@ -135,8 +141,9 @@ class Builder
* @param $utopia
* @param $injections
* @return Type
* @throws \Exception
*/
protected static function getArgType($validator, bool $required, $utopia, $injections): Type
private static function getParameterArgType($validator, bool $required, $utopia, $injections): Type
{
$validator = \is_callable($validator)
? \call_user_func_array($validator, $utopia->getResources($injections))
@ -158,13 +165,15 @@ class Builder
$type = Type::boolean();
break;
case 'Utopia\Validator\ArrayList':
$type = Type::listOf(self::json());
$nested = (fn() => $this->validator)->bindTo($validator, $validator)();
$type = Type::listOf(self::getParameterArgType($nested, $required, $utopia, $injections));
break;
case 'Utopia\Validator\Numeric':
case 'Utopia\Validator\Range':
$type = Type::int();
break;
case 'Utopia\Validator\Assoc':
case 'Utopia\Validator\JSON':
default:
$type = self::json();
break;
@ -177,6 +186,35 @@ class Builder
return $type;
}
/**
* Function to map an attribute type to a valid GraphQL Type
*
* @param $validator
* @param bool $required
* @param $utopia
* @param $injections
* @return Type
* @throws \Exception
*/
private static function getAttributeArgType($type, $array, $required): Type
{
if ($array) {
return Type::listOf(self::getAttributeArgType($type, false, $required));
}
$type = match ($type) {
'boolean' => Type::boolean(),
'integer' => Type::int(),
'double' => Type::float(),
default => Type::string(),
};
if ($required) {
$type = Type::nonNull($type);
}
return $type;
}
/**
* @throws \Exception
*/
@ -186,7 +224,8 @@ class Builder
Database $dbForProject
): Schema
{
Console::info("[INFO] Appending GraphQL Database Schema...");
Console::info("[INFO] Merging Schema...");
$start = microtime(true);
$db = self::buildCollectionsSchema($register, $dbForProject);
@ -211,39 +250,12 @@ class Builder
]);
$time_elapsed_secs = microtime(true) - $start;
Console::info("[INFO] Time Taken To Append Database to API Schema : ${time_elapsed_secs}s");
Console::info("[INFO] Time Taken To Merge Schema : ${time_elapsed_secs}s");
return $schema;
}
/**
* @throws \Exception
*/
public static function buildSchema($utopia, $response, $register, $dbForProject): Schema
{
$db = self::buildCollectionsSchema($register, $dbForProject);
$api = self::buildAPISchema($utopia, $response, $register);
$queryFields = \array_merge($api['query'], $db['query']);
$mutationFields = \array_merge($api['mutation'], $db['mutation']);
ksort($queryFields);
ksort($mutationFields);
return new Schema([
'query' => new ObjectType([
'name' => 'Query',
'description' => 'The root of all queries',
'fields' => $queryFields
]),
'mutation' => new ObjectType([
'name' => 'Mutation',
'description' => 'The root of all mutations',
'fields' => $mutationFields
])
]);
}
/**
* This function goes through all the project attributes and builds a
* GraphQL schema for all the collections they make up.
@ -255,116 +267,91 @@ class Builder
*/
public static function buildCollectionsSchema(Registry &$register, Database $dbForProject): array
{
Console::log("[INFO] Building GraphQL Database Schema...");
Console::info("[INFO] Building GraphQL Project Collection Schema...");
$start = microtime(true);
$collections = [];
$queryFields = [];
$mutationFields = [];
$limit = 50;
$offset = 0;
$attrs = Authorization::skip(static fn() => $dbForProject->find('attributes', [new Query('collectionId', Query::TYPE_EQUAL, ['movies'])]));
Authorization::skip(function () use ($mutationFields, $queryFields, $collections, $register, $offset, $dbForProject) {
Authorization::skip(function () use (&$mutationFields, &$queryFields, &$collections, $register, $limit, $offset, $dbForProject) {
while (!empty($attrs = $dbForProject->find(
'attributes',
limit: $dbForProject->getAttributeLimit(),
limit: $limit,
offset: $offset
))) {
go(function ($attrs, $dbForProject, $register, $collections, $queryFields, $mutationFields) {
foreach ($attrs as $attr) {
go(function ($attr, &$collections) {
/** @var Document $attr */
foreach ($attrs as $attr) {
$collectionId = $attr->getAttribute('collectionId');
$collectionId = $attr->getAttribute('collectionId');
if (isset(self::$typeMapping[$collectionId])) {
return;
}
if ($attr->getAttribute('status') !== 'available') {
return;
}
$key = $attr->getAttribute('key');
$type = $attr->getAttribute('type');
$escapedKey = str_replace('$', '_', $key);
$collections[$collectionId][$escapedKey] = [
'type' => $type,
'resolve' => function ($object, $args, $context, $info) use ($key) {
return $object->getAttribute($key);
}
];
}, $attr, $collections);
if ($attr->getAttribute('status') !== 'available') {
return;
}
foreach ($collections as $collectionId => $attributes) {
go(function ($collectionId, $attributes, $dbForProject, $register, &$queryFields, &$mutationFields) {
if (isset(self::$typeMapping[$collectionId])) {
return;
}
$key = $attr->getAttribute('key');
$type = $attr->getAttribute('type');
$array = $attr->getAttribute('array');
$required = $attr->getAttribute('required');
$objectType = new ObjectType([
'name' => \ucfirst($collectionId),
'fields' => $attributes
]);
$escapedKey = str_replace('$', '_', $key);
self::$typeMapping[$collectionId] = $objectType;
$collections[$collectionId][$escapedKey] = [
'type' => self::getAttributeArgType($type, $array, $required),
'resolve' => function ($object, $args, $context, $info) use ($key) {
return $object->getAttribute($key);
}
];
}
$mutateArgs = [];
foreach ($collections as $collectionId => $attributes) {
$objectType = new ObjectType([
'name' => $collectionId,
'fields' => $attributes
]);
foreach ($attributes as $name => $attribute) {
$mutateArgs[$name] = [
'type' => $attribute['type']
];
}
$idArgs = [
'id' => [
'type' => Type::string()
]
];
$idArgs = [
'id' => [
'type' => Type::string()
]
];
$listArgs = [
'limit' => [
'type' => Type::int(),
'defaultValue' => $limit,
],
'offset' => [
'type' => Type::int(),
'defaultValue' => 0,
],
'cursor' => [
'type' => Type::string(),
'defaultValue' => null,
],
'orderAttributes' => [
'type' => Type::listOf(Type::string()),
'defaultValue' => [],
],
'orderType' => [
'types' => Type::listOf(Type::string()),
'defaultValue' => [],
]
];
$listArgs = [
'limit' => [
'type' => Type::int()
],
'offset' => [
'type' => Type::int()
],
'cursor' => [
'type' => Type::string()
],
'orderAttributes' => [
'type' => Type::listOf(Type::string())
],
'orderType' => [
'types' => Type::listOf(Type::string())
]
];
self::createCollectionGetQuery($collectionId, $register, $dbForProject, $idArgs, $queryFields, $objectType);
self::createCollectionListQuery($collectionId, $register, $dbForProject, $listArgs, $queryFields, $objectType);
self::createCollectionCreateMutation($collectionId, $register, $dbForProject, $attributes, $mutationFields, $objectType);
self::createCollectionUpdateMutation($collectionId, $register, $dbForProject, $attributes, $mutationFields, $objectType);
self::createCollectionDeleteMutation($collectionId, $register, $dbForProject, $idArgs, $mutationFields, $objectType);
}
self::createCollectionGetQuery($collectionId, $register, $dbForProject, $idArgs, $queryFields);
self::createCollectionListQuery($collectionId, $register, $dbForProject, $listArgs, $queryFields);
self::createCollectionCreateMutation($collectionId, $register, $dbForProject, $mutateArgs, $mutationFields);
self::createCollectionUpdateMutation($collectionId, $register, $dbForProject, $mutateArgs, $mutationFields);
self::createCollectionDeleteMutation($collectionId, $register, $dbForProject, $idArgs, $mutationFields);
}, $collectionId, $attributes, $dbForProject, $register, $queryFields, $mutationFields);
}
}, $attrs, $dbForProject, $register, $collections, $queryFields, $mutationFields);
$offset += $dbForProject->getAttributeLimit();
$offset += $limit;
}
});
$time_elapsed_secs = microtime(true) - $start;
Console::log("[INFO] Time Taken To Build Database Schema : ${time_elapsed_secs}s");
Console::info('[INFO] Schema : ' . json_encode([
'query' => $queryFields,
'mutation' => $mutationFields
]));
Console::info("[INFO] Time Taken To Build Project Collection Schema : ${time_elapsed_secs}s");
return [
'query' => $queryFields,
@ -372,102 +359,103 @@ class Builder
];
}
private static function createCollectionGetQuery($collectionId, $register, $dbForProject, $args, &$queryFields)
private static function createCollectionGetQuery($collectionId, $register, $dbForProject, $args, &$queryFields, $objectType)
{
$resolve = function ($type, $args, $context, $info) use ($collectionId, &$register, $dbForProject) {
return SwoolePromise::create(function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
$resolve = fn($type, $args, $context, $info) => new SwoolePromise(
function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
try {
$resolve($dbForProject->getDocument($collectionId, $args['id']));
} catch (\Throwable $e) {
$reject($e);
}
});
};
}
);
$get = [
'type' => \ucfirst($collectionId),
'type' => $objectType,
'args' => $args,
'resolve' => $resolve
];
$queryFields['get' . \ucfirst($collectionId)] = $get;
$queryFields[$collectionId . 'Get'] = $get;
}
private static function createCollectionListQuery($collectionId, $register, $dbForProject, $args, &$queryFields)
private static function createCollectionListQuery($collectionId, $register, $dbForProject, $args, &$queryFields, $objectType)
{
$resolve = function ($type, $args, $context, $info) use ($collectionId, &$register, $dbForProject) {
return SwoolePromise::create(function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
$resolve = fn($type, $args, $context, $info) => new SwoolePromise(
function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
try {
$resolve($dbForProject->getCollection($collectionId));
} catch (\Throwable $e) {
$reject($e);
}
});
};
}
);
$list = [
'type' => \ucfirst($collectionId),
'type' => $objectType,
'args' => $args,
'resolve' => $resolve
];
$queryFields['list' . \ucfirst($collectionId)] = $list;
$queryFields[$collectionId . 'List'] = $list;
}
private static function createCollectionCreateMutation($collectionId, $register, $dbForProject, $args, &$mutationFields)
private static function createCollectionCreateMutation($collectionId, $register, $dbForProject, $args, &$mutationFields, $objectType)
{
$resolve = function ($type, $args, $context, $info) use ($collectionId, &$register, $dbForProject) {
return SwoolePromise::create(function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
$resolve = fn($type, $args, $context, $info) => new SwoolePromise(
function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
try {
$resolve($dbForProject->createDocument($collectionId, new Document($args)));
} catch (\Throwable $e) {
$reject($e);
}
});
};
}
);
$create = [
'type' => \ucfirst($collectionId),
'type' => $objectType,
'args' => $args,
'resolve' => $resolve
];
$mutationFields['create' . \ucfirst($collectionId)] = $create;
$mutationFields[$collectionId . 'Create'] = $create;
}
private static function createCollectionUpdateMutation($collectionId, $register, $dbForProject, $args, &$mutationFields)
private static function createCollectionUpdateMutation($collectionId, $register, $dbForProject, $args, &$mutationFields, $objectType)
{
$resolve = function ($type, $args, $context, $info) use ($collectionId, &$register, $dbForProject) {
return SwoolePromise::create(function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
$resolve = fn($type, $args, $context, $info) => new SwoolePromise(
function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
try {
$resolve($dbForProject->updateDocument($collectionId, $args['id'], new Document($args)));
} catch (\Throwable $e) {
$reject($e);
}
});
};
}
);
$update = [
'type' => \ucfirst($collectionId),
'type' => $objectType,
'args' => $args,
'resolve' => $resolve
];
$mutationFields['update' . \ucfirst($collectionId)] = $update;
$mutationFields[$collectionId . 'Update'] = $update;
}
private static function createCollectionDeleteMutation($collectionId, $register, $dbForProject, $args, &$mutationFields)
private static function createCollectionDeleteMutation($collectionId, $register, $dbForProject, $args, &$mutationFields, $objectType)
{
$resolve = function ($type, $args, $context, $info) use ($collectionId, &$register, $dbForProject) {
return SwoolePromise::create(function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
$resolve = fn($type, $args, $context, $info) => new SwoolePromise(
function (callable $resolve, callable $reject) use ($collectionId, $type, $args, $dbForProject) {
try {
$resolve($dbForProject->deleteDocument($collectionId, $args['id']));
} catch (\Throwable $e) {
$reject($e);
}
});
};
}
);
$delete = [
'type' => \ucfirst($collectionId),
'type' => $objectType,
'args' => $args,
'resolve' => $resolve
];
$mutationFields['delete' . \ucfirst($collectionId)] = $delete;
$mutationFields[$collectionId . 'Delete'] = $delete;
}
/**
@ -475,14 +463,15 @@ class Builder
* GraphQL schema for all those routes whose response model is neither empty nor NONE
*
* @param App $utopia
* @param Request $request
* @param Response $response
* @param Registry $register
* @return array
* @throws \Exception
*/
public static function buildAPISchema(App $utopia, Response $response, Registry $register): array
public static function buildAPISchema(App $utopia, Request $request, Response $response, Registry $register): array
{
Console::log("[INFO] Building GraphQL API Schema...");
Console::info("[INFO] Building GraphQL REST API Schema...");
$start = microtime(true);
self::init();
@ -491,66 +480,73 @@ class Builder
foreach ($utopia->getRoutes() as $method => $routes) {
foreach ($routes as $route) {
if (str_starts_with($route->getPath(), '/v1/mock/')) {
continue;
}
$namespace = $route->getLabel('sdk.namespace', '');
$methodName = $namespace . \ucfirst($route->getLabel('sdk.method', ''));
$responseModelName = $route->getLabel('sdk.response.model', "none");
$responseModelNames = $route->getLabel('sdk.response.model', "none");
Console::info("Namespace: $namespace");
Console::info("Method: $methodName");
Console::info("Response Model: $responseModelName");
Console::info("Raw routes: " . \json_encode($routes));
Console::info("Raw route: " . \json_encode($route));
if ($responseModelNames !== "none") {
$responseModels = \is_array($responseModelNames)
? \array_map(static fn($m) => $response->getModel($m), $responseModelNames)
: [$response->getModel($responseModelNames)];
if ($responseModelName !== "none") {
$responseModel = $response->getModel($responseModelName);
foreach ($responseModels as $responseModel) {
$type = self::getTypeMapping($responseModel, $response);
$description = $route->getDesc();
$args = [];
/* Create a GraphQL type for the current response model */
$type = self::getTypeMapping($responseModel, $response);
/* Get a description for this type */
$description = $route->getDesc();
/* Create the args required for this type */
$args = [];
foreach ($route->getParams() as $key => $value) {
$args[$key] = [
'type' => self::getArgType($value['validator'], !$value['optional'], $utopia, $value['injections']),
'description' => $value['description'],
'defaultValue' => $value['default']
];
}
/* Define a resolve function that defines how to fetch data for this type */
$resolve = function ($type, $args, $context, $info) use ($utopia, $response, &$register, $route) {
return SwoolePromise::create(function (callable $resolve, callable $reject) use ($utopia, $response, &$register, $route, $args) {
$utopia->setRoute($route)->execute($route, $args);
$result = $response->getPayload();
foreach ($route->getParams() as $key => $value) {
$args[$key] = [
'type' => self::getParameterArgType(
$value['validator'],
!$value['optional'],
$utopia,
$value['injections']
),
'description' => $value['description'],
'defaultValue' => $value['default']
];
}
if ($response->getCurrentModel() == Response::MODEL_ERROR_DEV) {
$reject(new ExceptionDev($result['message'], $result['code'], $result['version'], $result['file'], $result['line'], $result['trace']));
} else if ($response->getCurrentModel() == Response::MODEL_ERROR) {
$reject(new \Exception($result['message'], $result['code']));
/* Define a resolve function that defines how to fetch data for this type */
$resolve = fn($type, $args, $context, $info) => new SwoolePromise(
function (callable $resolve, callable $reject) use ($utopia, $request, $response, &$register, $route, $args) {
$utopia
->setRoute($route)
->execute($route, $request);
$result = $response->getPayload();
if ($response->getCurrentModel() == Response::MODEL_ERROR_DEV) {
$reject(new ExceptionDev($result['message'], $result['code'], $result['version'], $result['file'], $result['line'], $result['trace']));
} else if ($response->getCurrentModel() == Response::MODEL_ERROR) {
$reject(new \Exception($result['message'], $result['code']));
}
$resolve($result);
}
);
$resolve($result);
});
};
$field = [
'type' => $type,
'description' => $description,
'args' => $args,
'resolve' => $resolve
];
$field = [
'type' => $type,
'description' => $description,
'args' => $args,
'resolve' => $resolve
];
if ($method == 'GET') {
$queryFields[$methodName] = $field;
} else if ($method == 'POST' || $method == 'PUT' || $method == 'PATCH' || $method == 'DELETE') {
$mutationFields[$methodName] = $field;
if ($method == 'GET') {
$queryFields[$methodName] = $field;
} else if ($method == 'POST' || $method == 'PUT' || $method == 'PATCH' || $method == 'DELETE') {
$mutationFields[$methodName] = $field;
}
}
}
}
}
$time_elapsed_secs = microtime(true) - $start;
Console::log("[INFO] Time Taken To Build API Schema : ${time_elapsed_secs}s");
Console::info("[INFO] Time Taken To Build REST API Schema : ${time_elapsed_secs}s");
return [
'query' => $queryFields,