2020-11-11 22:02:42 +00:00
|
|
|
<?php
|
|
|
|
|
|
2025-02-04 11:08:56 +00:00
|
|
|
namespace Appwrite\SDK\Specification\Format;
|
2020-11-11 22:02:42 +00:00
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
use Appwrite\SDK\AuthType;
|
2025-03-27 08:30:10 +00:00
|
|
|
use Appwrite\SDK\Method;
|
2025-01-17 04:31:39 +00:00
|
|
|
use Appwrite\SDK\MethodType;
|
2025-03-27 08:30:10 +00:00
|
|
|
use Appwrite\SDK\Response;
|
2025-02-04 11:08:56 +00:00
|
|
|
use Appwrite\SDK\Specification\Format;
|
2020-11-11 22:02:42 +00:00
|
|
|
use Appwrite\Template\Template;
|
2022-06-29 23:41:49 +00:00
|
|
|
use Appwrite\Utopia\Response\Model;
|
2022-12-14 16:04:06 +00:00
|
|
|
use Utopia\Database\Helpers\Permission;
|
|
|
|
|
use Utopia\Database\Helpers\Role;
|
2024-10-08 07:54:40 +00:00
|
|
|
use Utopia\Validator;
|
|
|
|
|
use Utopia\Validator\ArrayList;
|
|
|
|
|
use Utopia\Validator\Nullable;
|
|
|
|
|
use Utopia\Validator\Range;
|
|
|
|
|
use Utopia\Validator\WhiteList;
|
2020-11-11 22:02:42 +00:00
|
|
|
|
|
|
|
|
class OpenAPI3 extends Format
|
|
|
|
|
{
|
2022-05-23 14:54:50 +00:00
|
|
|
public function getName(): string
|
2020-11-11 22:02:42 +00:00
|
|
|
{
|
|
|
|
|
return 'Open API 3';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function parse(): array
|
|
|
|
|
{
|
2022-01-04 10:42:23 +00:00
|
|
|
/**
|
2022-06-29 23:41:49 +00:00
|
|
|
* Specifications (v3.0.0):
|
|
|
|
|
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
|
|
|
|
*/
|
2020-11-11 22:02:42 +00:00
|
|
|
$output = [
|
|
|
|
|
'openapi' => '3.0.0',
|
|
|
|
|
'info' => [
|
|
|
|
|
'version' => $this->getParam('version'),
|
|
|
|
|
'title' => $this->getParam('name'),
|
|
|
|
|
'description' => $this->getParam('description'),
|
|
|
|
|
'termsOfService' => $this->getParam('terms'),
|
|
|
|
|
'contact' => [
|
|
|
|
|
'name' => $this->getParam('contact.name'),
|
|
|
|
|
'url' => $this->getParam('contact.url'),
|
|
|
|
|
'email' => $this->getParam('contact.email'),
|
|
|
|
|
],
|
|
|
|
|
'license' => [
|
|
|
|
|
'name' => 'BSD-3-Clause',
|
|
|
|
|
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
'servers' => [
|
|
|
|
|
[
|
|
|
|
|
'url' => $this->getParam('endpoint', ''),
|
|
|
|
|
],
|
2025-04-24 11:15:23 +00:00
|
|
|
[
|
|
|
|
|
'url' => $this->getParam('endpoint.docs', ''),
|
|
|
|
|
],
|
2020-11-11 22:02:42 +00:00
|
|
|
],
|
|
|
|
|
'paths' => [],
|
2021-01-26 11:54:06 +00:00
|
|
|
'tags' => $this->services,
|
2020-11-11 22:02:42 +00:00
|
|
|
'components' => [
|
|
|
|
|
'schemas' => [],
|
2020-11-14 11:52:38 +00:00
|
|
|
'securitySchemes' => $this->keys,
|
2020-11-11 22:02:42 +00:00
|
|
|
],
|
|
|
|
|
'externalDocs' => [
|
|
|
|
|
'description' => $this->getParam('docs.description'),
|
|
|
|
|
'url' => $this->getParam('docs.url'),
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if (isset($output['components']['securitySchemes']['Project'])) {
|
2024-05-07 18:55:58 +00:00
|
|
|
$output['components']['securitySchemes']['Project']['x-appwrite'] = ['demo' => '<YOUR_PROJECT_ID>'];
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
if (isset($output['components']['securitySchemes']['Key'])) {
|
2024-05-07 18:55:58 +00:00
|
|
|
$output['components']['securitySchemes']['Key']['x-appwrite'] = ['demo' => '<YOUR_API_KEY>'];
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
2021-03-28 21:47:17 +00:00
|
|
|
|
|
|
|
|
if (isset($output['securityDefinitions']['JWT'])) {
|
2024-05-07 18:55:58 +00:00
|
|
|
$output['securityDefinitions']['JWT']['x-appwrite'] = ['demo' => '<YOUR_JWT>'];
|
2021-03-28 21:47:17 +00:00
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
if (isset($output['components']['securitySchemes']['Locale'])) {
|
|
|
|
|
$output['components']['securitySchemes']['Locale']['x-appwrite'] = ['demo' => 'en'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($output['components']['securitySchemes']['Mode'])) {
|
|
|
|
|
$output['components']['securitySchemes']['Mode']['x-appwrite'] = ['demo' => ''];
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 08:46:45 +00:00
|
|
|
$usedModels = [];
|
|
|
|
|
|
2022-06-29 23:41:49 +00:00
|
|
|
foreach ($this->routes as $route) {
|
2021-08-19 05:09:55 +00:00
|
|
|
$url = \str_replace('/v1', '', $route->getPath());
|
2020-11-11 22:02:42 +00:00
|
|
|
$scope = $route->getLabel('scope', '');
|
|
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
$sdk = $route->getLabel('sdk', false);
|
2020-11-11 22:02:42 +00:00
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
if (empty($sdk)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$additionalMethods = null;
|
2025-03-27 08:30:10 +00:00
|
|
|
if (\is_array($sdk)) {
|
2025-01-17 04:31:39 +00:00
|
|
|
$additionalMethods = $sdk;
|
2025-01-24 07:19:43 +00:00
|
|
|
$sdk = $sdk[0];
|
2025-01-17 04:31:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2025-03-27 08:30:10 +00:00
|
|
|
* @var Method $sdk
|
2025-01-17 04:31:39 +00:00
|
|
|
*/
|
2025-03-27 08:30:10 +00:00
|
|
|
$consumes = [$sdk->getRequestType()->value];
|
2025-01-17 04:31:39 +00:00
|
|
|
|
|
|
|
|
$method = $sdk->getMethodName() ?? \uniqid();
|
|
|
|
|
|
2025-03-27 08:30:10 +00:00
|
|
|
if (!empty($method) && \is_array($method)) {
|
|
|
|
|
$method = \array_keys($method)[0];
|
2025-01-17 04:31:39 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-16 10:45:58 +00:00
|
|
|
$desc = $sdk->getDescriptionFilePath() ?: $sdk->getDescription();
|
2025-01-17 04:31:39 +00:00
|
|
|
$produces = ($sdk->getContentType())->value;
|
|
|
|
|
$routeSecurity = $sdk->getAuth() ?? [];
|
2022-06-29 23:41:49 +00:00
|
|
|
$sdkPlatforms = [];
|
2021-05-19 13:10:32 +00:00
|
|
|
|
|
|
|
|
foreach ($routeSecurity as $value) {
|
|
|
|
|
switch ($value) {
|
2025-01-17 04:31:39 +00:00
|
|
|
case AuthType::SESSION:
|
2022-06-29 23:41:49 +00:00
|
|
|
$sdkPlatforms[] = APP_PLATFORM_CLIENT;
|
2021-05-19 13:10:32 +00:00
|
|
|
break;
|
2025-01-17 04:31:39 +00:00
|
|
|
case AuthType::JWT:
|
2025-03-27 08:30:10 +00:00
|
|
|
case AuthType::KEY:
|
2022-06-29 23:41:49 +00:00
|
|
|
$sdkPlatforms[] = APP_PLATFORM_SERVER;
|
2021-05-19 13:10:32 +00:00
|
|
|
break;
|
2025-01-17 04:31:39 +00:00
|
|
|
case AuthType::ADMIN:
|
2022-06-29 23:41:49 +00:00
|
|
|
$sdkPlatforms[] = APP_PLATFORM_CONSOLE;
|
2021-05-19 13:10:32 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-19 15:29:06 +00:00
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (empty($routeSecurity)) {
|
2024-02-24 14:38:09 +00:00
|
|
|
$sdkPlatforms[] = APP_PLATFORM_SERVER;
|
|
|
|
|
$sdkPlatforms[] = APP_PLATFORM_CLIENT;
|
2021-05-19 15:29:06 +00:00
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
$namespace = $sdk->getNamespace() ?? 'default';
|
|
|
|
|
|
2025-04-15 12:04:29 +00:00
|
|
|
$desc ??= '';
|
2025-02-05 11:27:20 +00:00
|
|
|
$descContents = \str_ends_with($desc, '.md') ? \file_get_contents($desc) : $desc;
|
|
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
$temp = [
|
|
|
|
|
'summary' => $route->getDesc(),
|
2025-01-17 04:31:39 +00:00
|
|
|
'operationId' => $namespace . ucfirst($method),
|
|
|
|
|
'tags' => [$namespace],
|
2025-02-05 11:27:20 +00:00
|
|
|
'description' => $descContents,
|
2020-11-14 11:52:38 +00:00
|
|
|
'responses' => [],
|
2020-11-11 22:02:42 +00:00
|
|
|
'x-appwrite' => [ // Appwrite related metadata
|
2024-02-25 10:13:28 +00:00
|
|
|
'method' => $method,
|
2025-03-31 09:32:47 +00:00
|
|
|
'group' => $sdk->getGroup(),
|
2023-08-30 16:36:47 +00:00
|
|
|
'weight' => $route->getOrder(),
|
2020-11-11 22:02:42 +00:00
|
|
|
'cookies' => $route->getLabel('sdk.cookies', false),
|
2025-01-17 04:31:39 +00:00
|
|
|
'type' => $sdk->getType()->value ?? '',
|
|
|
|
|
'deprecated' => $sdk->isDeprecated(),
|
|
|
|
|
'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($method) . '.md',
|
|
|
|
|
'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $sdk->getDescription() ?? '',
|
2020-11-11 22:02:42 +00:00
|
|
|
'rate-limit' => $route->getLabel('abuse-limit', 0),
|
|
|
|
|
'rate-time' => $route->getLabel('abuse-time', 3600),
|
|
|
|
|
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
|
|
|
|
|
'scope' => $route->getLabel('scope', ''),
|
2022-06-29 23:41:49 +00:00
|
|
|
'platforms' => $sdkPlatforms,
|
2025-01-17 04:31:39 +00:00
|
|
|
'packaging' => $sdk->isPackaging()
|
2020-11-11 22:02:42 +00:00
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
|
|
|
|
|
if (!empty($additionalMethods)) {
|
2025-01-24 07:19:43 +00:00
|
|
|
$temp['x-appwrite']['methods'] = [];
|
2025-01-17 04:31:39 +00:00
|
|
|
foreach ($additionalMethods as $method) {
|
2025-03-27 08:30:10 +00:00
|
|
|
/** @var Method $method */
|
2025-01-24 07:19:43 +00:00
|
|
|
$desc = $method->getDescriptionFilePath();
|
2025-01-17 04:31:39 +00:00
|
|
|
$additionalMethod = [
|
|
|
|
|
'name' => $method->getMethodName(),
|
2025-05-16 15:40:51 +00:00
|
|
|
'auth' => \array_merge(...\array_map(fn ($auth) => [$auth->value => []], $method->getAuth())),
|
2025-01-17 04:31:39 +00:00
|
|
|
'parameters' => [],
|
|
|
|
|
'required' => [],
|
2025-01-24 07:19:43 +00:00
|
|
|
'responses' => [],
|
|
|
|
|
'description' => ($desc) ? \file_get_contents($desc) : '',
|
2025-01-17 04:31:39 +00:00
|
|
|
];
|
|
|
|
|
|
2025-03-27 08:30:10 +00:00
|
|
|
foreach ($method->getParameters() as $parameter) {
|
|
|
|
|
$additionalMethod['parameters'][] = $parameter->getName();
|
2025-01-17 04:31:39 +00:00
|
|
|
|
2025-05-05 11:26:59 +00:00
|
|
|
if (!$parameter->getOptional()) {
|
2025-03-27 08:30:10 +00:00
|
|
|
$additionalMethod['required'][] = $parameter->getName();
|
2025-01-17 04:31:39 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($method->getResponses() as $response) {
|
2025-01-30 05:19:20 +00:00
|
|
|
if (\is_array($response->getModel())) {
|
|
|
|
|
$additionalMethod['responses'][] = [
|
|
|
|
|
'code' => $response->getCode(),
|
|
|
|
|
'model' => \array_map(fn ($m) => '#/components/schemas/' . $m, $response->getModel())
|
|
|
|
|
];
|
|
|
|
|
} else {
|
|
|
|
|
$additionalMethod['responses'][] = [
|
|
|
|
|
'code' => $response->getCode(),
|
|
|
|
|
'model' => '#/components/schemas/' . $response->getModel()
|
|
|
|
|
];
|
|
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
}
|
2025-01-17 04:31:39 +00:00
|
|
|
|
2025-01-24 07:19:43 +00:00
|
|
|
$temp['x-appwrite']['methods'][] = $additionalMethod;
|
2020-11-14 11:52:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
// Handle response models
|
|
|
|
|
foreach ($sdk->getResponses() as $response) {
|
2025-03-27 08:30:10 +00:00
|
|
|
/** @var Response $response */
|
2025-01-17 04:31:39 +00:00
|
|
|
$model = $response->getModel();
|
|
|
|
|
|
|
|
|
|
foreach ($this->models as $value) {
|
|
|
|
|
if (\is_array($model)) {
|
|
|
|
|
$model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model);
|
|
|
|
|
} else {
|
|
|
|
|
if ($value->getType() === $model) {
|
|
|
|
|
$model = $value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
}
|
2025-01-17 04:31:39 +00:00
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
if (!(\is_array($model)) && $model->isNone()) {
|
|
|
|
|
$temp['responses'][(string)$response->getCode() ?? '500'] = [
|
|
|
|
|
'description' => in_array($produces, [
|
|
|
|
|
'image/*',
|
|
|
|
|
'image/jpeg',
|
|
|
|
|
'image/gif',
|
|
|
|
|
'image/png',
|
|
|
|
|
'image/webp',
|
|
|
|
|
'image/svg-x',
|
|
|
|
|
'image/x-icon',
|
|
|
|
|
'image/bmp',
|
|
|
|
|
]) ? 'Image' : 'File',
|
2021-09-30 09:59:01 +00:00
|
|
|
];
|
|
|
|
|
} else {
|
2025-01-17 04:31:39 +00:00
|
|
|
if (\is_array($model)) {
|
|
|
|
|
$modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model));
|
|
|
|
|
|
|
|
|
|
// model has multiple possible responses, we will use oneOf
|
|
|
|
|
foreach ($model as $m) {
|
|
|
|
|
$usedModels[] = $m->getType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$temp['responses'][(string)$response->getCode() ?? '500'] = [
|
|
|
|
|
'description' => $modelDescription,
|
|
|
|
|
'content' => [
|
|
|
|
|
$produces => [
|
|
|
|
|
'schema' => [
|
|
|
|
|
'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model)
|
|
|
|
|
],
|
2021-09-30 09:59:01 +00:00
|
|
|
],
|
|
|
|
|
],
|
2025-01-17 04:31:39 +00:00
|
|
|
];
|
|
|
|
|
} else {
|
|
|
|
|
// Response definition using one type
|
|
|
|
|
$usedModels[] = $model->getType();
|
|
|
|
|
$temp['responses'][(string)$response->getCode() ?? '500'] = [
|
|
|
|
|
'description' => $model->getName(),
|
|
|
|
|
'content' => [
|
|
|
|
|
$produces => [
|
|
|
|
|
'schema' => [
|
|
|
|
|
'$ref' => '#/components/schemas/' . $model->getType(),
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
}
|
2020-11-14 11:52:38 +00:00
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
if (($response->getCode() ?? 500) === 204) {
|
|
|
|
|
$temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content';
|
|
|
|
|
unset($temp['responses'][(string)$response->getCode() ?? '500']['schema']);
|
|
|
|
|
}
|
2020-11-14 11:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
2025-03-27 08:30:10 +00:00
|
|
|
if ((!empty($scope))) {
|
2021-03-28 21:22:12 +00:00
|
|
|
$securities = ['Project' => []];
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2025-01-17 04:31:39 +00:00
|
|
|
foreach ($sdk->getAuth() as $security) {
|
2025-03-27 08:30:10 +00:00
|
|
|
/** @var AuthType $security */
|
2025-01-17 04:31:39 +00:00
|
|
|
if (array_key_exists($security->value, $this->keys)) {
|
|
|
|
|
$securities[$security->value] = [];
|
2021-03-28 21:22:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
2021-03-28 21:47:17 +00:00
|
|
|
|
2021-05-19 14:26:06 +00:00
|
|
|
$temp['x-appwrite']['auth'] = array_slice($securities, 0, $this->authCount);
|
2021-03-28 21:22:12 +00:00
|
|
|
$temp['security'][] = $securities;
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
2020-11-14 11:52:38 +00:00
|
|
|
$body = [
|
|
|
|
|
'content' => [
|
|
|
|
|
$consumes[0] => [
|
|
|
|
|
'schema' => [
|
|
|
|
|
'type' => 'object',
|
|
|
|
|
'properties' => [],
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$bodyRequired = [];
|
|
|
|
|
|
|
|
|
|
foreach ($route->getParams() as $name => $param) { // Set params
|
2024-10-08 07:54:40 +00:00
|
|
|
/**
|
|
|
|
|
* @var \Utopia\Validator $validator
|
|
|
|
|
*/
|
|
|
|
|
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
|
2020-11-11 22:02:42 +00:00
|
|
|
|
|
|
|
|
$node = [
|
|
|
|
|
'name' => $name,
|
|
|
|
|
'description' => $param['description'],
|
|
|
|
|
'required' => !$param['optional'],
|
|
|
|
|
];
|
|
|
|
|
|
2023-03-13 10:24:49 +00:00
|
|
|
$isNullable = $validator instanceof Nullable;
|
|
|
|
|
|
|
|
|
|
if ($isNullable) {
|
|
|
|
|
/** @var Nullable $validator */
|
2023-03-10 10:06:10 +00:00
|
|
|
$validator = $validator->getValidator();
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
switch ((!empty($validator)) ? \get_class($validator) : '') {
|
2024-02-02 11:33:48 +00:00
|
|
|
case 'Utopia\Database\Validator\UID':
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\Text':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2024-02-25 08:12:28 +00:00
|
|
|
$node['schema']['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\Boolean':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['x-example'] = false;
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2022-01-18 11:05:04 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\CustomId':
|
2025-01-17 04:31:39 +00:00
|
|
|
if ($sdk->getType() === MethodType::UPLOAD) {
|
2022-02-11 00:30:08 +00:00
|
|
|
$node['schema']['x-upload-id'] = true;
|
|
|
|
|
}
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2024-02-25 08:12:28 +00:00
|
|
|
$node['schema']['x-example'] = '<' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . '>';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2022-07-28 12:38:54 +00:00
|
|
|
case 'Utopia\Database\Validator\DatetimeValidator':
|
|
|
|
|
$node['schema']['type'] = $validator->getType();
|
|
|
|
|
$node['schema']['format'] = 'datetime';
|
2022-08-30 09:38:27 +00:00
|
|
|
$node['schema']['x-example'] = Model::TYPE_DATETIME_EXAMPLE;
|
2022-07-28 12:38:54 +00:00
|
|
|
break;
|
2021-04-21 06:54:28 +00:00
|
|
|
case 'Appwrite\Network\Validator\Email':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['format'] = 'email';
|
|
|
|
|
$node['schema']['x-example'] = 'email@example.com';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\Host':
|
|
|
|
|
case 'Utopia\Validator\URL':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['format'] = 'url';
|
|
|
|
|
$node['schema']['x-example'] = 'https://example.com';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\JSON':
|
|
|
|
|
case 'Utopia\Validator\Mock':
|
|
|
|
|
case 'Utopia\Validator\Assoc':
|
2021-10-05 15:39:39 +00:00
|
|
|
$param['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
|
2021-05-21 08:44:51 +00:00
|
|
|
$node['schema']['type'] = 'object';
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['x-example'] = '{}';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2021-01-22 08:28:33 +00:00
|
|
|
case 'Utopia\Storage\Validator\File':
|
2020-11-14 11:52:38 +00:00
|
|
|
$consumes = ['multipart/form-data'];
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['format'] = 'binary';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\ArrayList':
|
2024-02-02 11:33:48 +00:00
|
|
|
/** @var ArrayList $validator */
|
|
|
|
|
$node['schema']['type'] = 'array';
|
|
|
|
|
$node['schema']['items'] = [
|
|
|
|
|
'type' => $validator->getValidator()->getType(),
|
|
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Attributes':
|
2022-08-31 13:32:34 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Buckets':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Collections':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Databases':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Deployments':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Executions':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Files':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Functions':
|
2024-02-02 11:33:48 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Identities':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Indexes':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Installations':
|
2022-08-31 13:32:34 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Memberships':
|
2024-02-02 11:33:48 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Messages':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Migrations':
|
2022-08-31 13:32:34 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Projects':
|
2024-02-02 11:33:48 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Providers':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Rules':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Subscribers':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Targets':
|
2022-08-31 13:32:34 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Teams':
|
2024-02-02 11:33:48 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Topics':
|
2022-08-31 13:32:34 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Users':
|
|
|
|
|
case 'Appwrite\Utopia\Database\Validator\Queries\Variables':
|
2023-04-27 11:59:05 +00:00
|
|
|
case 'Utopia\Database\Validator\Queries':
|
2024-02-02 11:33:48 +00:00
|
|
|
case 'Utopia\Database\Validator\Queries\Document':
|
|
|
|
|
case 'Utopia\Database\Validator\Queries\Documents':
|
2021-05-21 08:44:51 +00:00
|
|
|
$node['schema']['type'] = 'array';
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['items'] = [
|
2020-11-11 22:02:42 +00:00
|
|
|
'type' => 'string',
|
|
|
|
|
];
|
|
|
|
|
break;
|
2021-11-18 11:49:54 +00:00
|
|
|
case 'Utopia\Database\Validator\Permissions':
|
|
|
|
|
$node['schema']['type'] = $validator->getType();
|
|
|
|
|
$node['schema']['items'] = [
|
|
|
|
|
'type' => 'string',
|
|
|
|
|
];
|
2022-08-22 02:27:17 +00:00
|
|
|
$node['schema']['x-example'] = '["' . Permission::read(Role::any()) . '"]';
|
|
|
|
|
break;
|
|
|
|
|
case 'Utopia\Database\Validator\Roles':
|
|
|
|
|
$node['schema']['type'] = $validator->getType();
|
|
|
|
|
$node['schema']['items'] = [
|
|
|
|
|
'type' => 'string',
|
|
|
|
|
];
|
|
|
|
|
$node['schema']['x-example'] = '["' . Role::any()->toString() . '"]';
|
2021-11-18 11:49:54 +00:00
|
|
|
break;
|
2020-11-11 22:02:42 +00:00
|
|
|
case 'Appwrite\Auth\Validator\Password':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2021-05-21 08:44:51 +00:00
|
|
|
$node['schema']['format'] = 'password';
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['x-example'] = 'password';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2022-10-03 15:06:44 +00:00
|
|
|
case 'Appwrite\Auth\Validator\Phone':
|
|
|
|
|
$node['schema']['type'] = $validator->getType();
|
|
|
|
|
$node['schema']['format'] = 'phone';
|
|
|
|
|
$node['schema']['x-example'] = '+12065550100'; // In the US, 555 is reserved like example.com
|
|
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\Range':
|
2024-02-02 11:33:48 +00:00
|
|
|
/** @var Range $validator */
|
2022-05-23 14:54:50 +00:00
|
|
|
$node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float';
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['x-example'] = $validator->getMin();
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\Numeric':
|
|
|
|
|
case 'Utopia\Validator\Integer':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['format'] = 'int32';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\FloatValidator':
|
2022-01-31 10:42:33 +00:00
|
|
|
$node['schema']['type'] = 'number';
|
|
|
|
|
$node['schema']['format'] = 'float';
|
|
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\Length':
|
2021-05-21 07:08:53 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-10-08 07:54:40 +00:00
|
|
|
case 'Utopia\Validator\WhiteList':
|
2024-02-02 11:33:48 +00:00
|
|
|
/** @var WhiteList $validator */
|
2021-04-13 08:46:30 +00:00
|
|
|
$node['schema']['type'] = $validator->getType();
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['x-example'] = $validator->getList()[0];
|
2021-04-13 08:46:30 +00:00
|
|
|
|
2023-08-11 07:43:46 +00:00
|
|
|
//Iterate from the blackList. If it matches with the current one, then it is a blackList
|
|
|
|
|
// Do not add the enum
|
2023-08-11 17:20:40 +00:00
|
|
|
$allowed = true;
|
|
|
|
|
foreach ($this->enumBlacklist as $blacklist) {
|
2023-08-14 23:35:18 +00:00
|
|
|
if (
|
2025-01-17 04:31:39 +00:00
|
|
|
$blacklist['namespace'] == $sdk->getNamespace()
|
2024-02-25 10:17:37 +00:00
|
|
|
&& $blacklist['method'] == $method
|
2023-08-14 23:35:18 +00:00
|
|
|
&& $blacklist['parameter'] == $name
|
|
|
|
|
) {
|
2023-08-11 17:20:40 +00:00
|
|
|
$allowed = false;
|
2023-08-11 07:43:46 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-15 01:57:48 +00:00
|
|
|
if ($allowed) {
|
2024-03-06 17:34:21 +00:00
|
|
|
$node['schema']['enum'] = $validator->getList();
|
2025-01-17 04:31:39 +00:00
|
|
|
$node['schema']['x-enum-name'] = $this->getEnumName($sdk->getNamespace() ?? '', $method, $name);
|
|
|
|
|
$node['schema']['x-enum-keys'] = $this->getEnumKeys($sdk->getNamespace() ?? '', $method, $name);
|
2023-07-19 16:17:23 +00:00
|
|
|
}
|
2021-04-13 08:46:30 +00:00
|
|
|
if ($validator->getType() === 'integer') {
|
|
|
|
|
$node['format'] = 'int32';
|
|
|
|
|
}
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2024-02-20 07:15:08 +00:00
|
|
|
case 'Appwrite\Utopia\Database\Validator\CompoundUID':
|
|
|
|
|
$node['schema']['type'] = $validator->getType();
|
|
|
|
|
$node['schema']['x-example'] = '[ID1:ID2]';
|
|
|
|
|
break;
|
2020-11-11 22:02:42 +00:00
|
|
|
default:
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['type'] = 'string';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
|
2020-11-14 11:52:38 +00:00
|
|
|
$node['schema']['default'] = $param['default'];
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (false !== \strpos($url, ':' . $name)) { // Param is in URL path
|
2020-11-11 22:02:42 +00:00
|
|
|
$node['in'] = 'path';
|
|
|
|
|
$temp['parameters'][] = $node;
|
|
|
|
|
} elseif ($route->getMethod() == 'GET') { // Param is in query
|
|
|
|
|
$node['in'] = 'query';
|
|
|
|
|
$temp['parameters'][] = $node;
|
|
|
|
|
} else { // Param is in payload
|
2022-05-23 14:54:50 +00:00
|
|
|
if (!$param['optional']) {
|
2020-11-14 11:52:38 +00:00
|
|
|
$bodyRequired[] = $name;
|
|
|
|
|
}
|
2020-11-11 22:02:42 +00:00
|
|
|
|
2020-11-14 11:52:38 +00:00
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name] = [
|
|
|
|
|
'type' => $node['schema']['type'],
|
|
|
|
|
'description' => $node['description'],
|
2022-02-20 09:22:42 +00:00
|
|
|
'x-example' => $node['schema']['x-example'] ?? null
|
2020-11-14 11:52:38 +00:00
|
|
|
];
|
|
|
|
|
|
2023-08-11 07:43:46 +00:00
|
|
|
if (isset($node['schema']['enum'])) {
|
|
|
|
|
/// If the enum flag is Set, add the enum values to the body
|
|
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['enum'] = $node['schema']['enum'];
|
|
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-enum-name'] = $node['schema']['x-enum-name'] ?? null;
|
|
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-enum-keys'] = $node['schema']['x-enum-keys'] ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if ($node['schema']['x-upload-id'] ?? false) {
|
2022-02-20 09:22:42 +00:00
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-upload-id'] = $node['schema']['x-upload-id'];
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (isset($node['default'])) {
|
2020-11-14 13:05:18 +00:00
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['default'] = $node['default'];
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (\array_key_exists('items', $node['schema'])) {
|
2020-11-14 11:52:38 +00:00
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['items'] = $node['schema']['items'];
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
2022-06-27 09:14:27 +00:00
|
|
|
|
|
|
|
|
if ($node['x-global'] ?? false) {
|
|
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-global'] = true;
|
|
|
|
|
}
|
2023-03-13 10:24:49 +00:00
|
|
|
|
|
|
|
|
if ($isNullable) {
|
|
|
|
|
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-nullable'] = true;
|
|
|
|
|
}
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
$url = \str_replace(':' . $name, '{' . $name . '}', $url);
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (!empty($bodyRequired)) {
|
2020-11-14 13:05:18 +00:00
|
|
|
$body['content'][$consumes[0]]['schema']['required'] = $bodyRequired;
|
|
|
|
|
}
|
2020-11-14 11:52:38 +00:00
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (!empty($body['content'][$consumes[0]]['schema']['properties'])) {
|
2020-11-14 11:52:38 +00:00
|
|
|
$temp['requestBody'] = $body;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
|
|
|
|
}
|
2022-01-04 10:42:23 +00:00
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
foreach ($this->models as $model) {
|
2022-06-29 23:41:49 +00:00
|
|
|
$this->getNestedModels($model, $usedModels);
|
2021-04-08 09:24:41 +00:00
|
|
|
}
|
2022-01-04 10:42:23 +00:00
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
foreach ($this->models as $model) {
|
2021-04-08 09:27:59 +00:00
|
|
|
if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') {
|
2021-04-08 08:46:45 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
$required = $model->getRequired();
|
|
|
|
|
$rules = $model->getRules();
|
|
|
|
|
|
|
|
|
|
$output['components']['schemas'][$model->getType()] = [
|
2020-11-14 11:52:38 +00:00
|
|
|
'description' => $model->getName(),
|
2020-11-11 22:02:42 +00:00
|
|
|
'type' => 'object',
|
|
|
|
|
];
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (!empty($rules)) {
|
2020-11-14 11:52:38 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['properties'] = [];
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if ($model->isAny()) {
|
2020-11-11 22:02:42 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['additionalProperties'] = true;
|
|
|
|
|
}
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (!empty($required)) {
|
2020-11-11 22:02:42 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['required'] = $required;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
foreach ($model->getRules() as $name => $rule) {
|
2020-11-11 22:02:42 +00:00
|
|
|
$type = '';
|
|
|
|
|
$format = null;
|
|
|
|
|
$items = null;
|
|
|
|
|
|
|
|
|
|
switch ($rule['type']) {
|
|
|
|
|
case 'string':
|
2022-07-28 12:38:54 +00:00
|
|
|
case 'datetime':
|
2024-09-26 11:59:41 +00:00
|
|
|
case 'payload':
|
2020-11-11 22:02:42 +00:00
|
|
|
$type = 'string';
|
|
|
|
|
break;
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2022-03-01 00:45:24 +00:00
|
|
|
case 'json':
|
|
|
|
|
$type = 'object';
|
|
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name]['additionalProperties'] = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
case 'integer':
|
|
|
|
|
$type = 'integer';
|
|
|
|
|
$format = 'int32';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'float':
|
|
|
|
|
$type = 'number';
|
|
|
|
|
$format = 'float';
|
|
|
|
|
break;
|
2021-09-21 12:25:41 +00:00
|
|
|
|
|
|
|
|
case 'double':
|
|
|
|
|
$type = 'number';
|
|
|
|
|
$format = 'double';
|
|
|
|
|
break;
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
case 'boolean':
|
2020-11-14 11:52:38 +00:00
|
|
|
$type = 'boolean';
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
2021-09-30 09:59:01 +00:00
|
|
|
|
2020-11-11 22:02:42 +00:00
|
|
|
default:
|
|
|
|
|
$type = 'object';
|
|
|
|
|
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if (\is_array($rule['type'])) {
|
|
|
|
|
if ($rule['array']) {
|
2021-09-23 11:12:50 +00:00
|
|
|
$items = [
|
2022-05-23 14:54:50 +00:00
|
|
|
'anyOf' => \array_map(function ($type) {
|
|
|
|
|
return ['$ref' => '#/components/schemas/' . $type];
|
2021-09-23 11:12:50 +00:00
|
|
|
}, $rule['type'])
|
|
|
|
|
];
|
|
|
|
|
} else {
|
|
|
|
|
$items = [
|
2022-05-23 14:54:50 +00:00
|
|
|
'oneOf' => \array_map(function ($type) {
|
|
|
|
|
return ['$ref' => '#/components/schemas/' . $type];
|
2021-09-23 11:12:50 +00:00
|
|
|
}, $rule['type'])
|
|
|
|
|
];
|
|
|
|
|
}
|
2021-09-21 12:01:18 +00:00
|
|
|
} else {
|
|
|
|
|
$items = [
|
2022-05-23 14:54:50 +00:00
|
|
|
'$ref' => '#/components/schemas/' . $rule['type'],
|
2021-09-21 12:01:18 +00:00
|
|
|
];
|
|
|
|
|
}
|
2020-11-11 22:02:42 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if ($rule['array']) {
|
2020-11-11 22:02:42 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name] = [
|
|
|
|
|
'type' => 'array',
|
|
|
|
|
'description' => $rule['description'] ?? '',
|
|
|
|
|
'items' => [
|
|
|
|
|
'type' => $type,
|
2021-01-31 23:07:11 +00:00
|
|
|
],
|
|
|
|
|
'x-example' => $rule['example'] ?? null,
|
2020-11-11 22:02:42 +00:00
|
|
|
];
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if ($format) {
|
2020-11-11 22:02:42 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name]['items']['format'] = $format;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name] = [
|
|
|
|
|
'type' => $type,
|
|
|
|
|
'description' => $rule['description'] ?? '',
|
2020-11-14 11:52:38 +00:00
|
|
|
'x-example' => $rule['example'] ?? null,
|
2020-11-11 22:02:42 +00:00
|
|
|
];
|
|
|
|
|
|
2022-05-23 14:54:50 +00:00
|
|
|
if ($format) {
|
2020-11-11 22:02:42 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name]['format'] = $format;
|
|
|
|
|
}
|
2022-03-01 00:45:24 +00:00
|
|
|
}
|
2022-05-23 14:54:50 +00:00
|
|
|
if ($items) {
|
2022-03-01 00:45:24 +00:00
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items;
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
2021-11-25 10:08:39 +00:00
|
|
|
if (!in_array($name, $required)) {
|
|
|
|
|
$output['components']['schemas'][$model->getType()]['properties'][$name]['nullable'] = true;
|
|
|
|
|
}
|
2020-11-11 22:02:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
\ksort($output['paths']);
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
}
|
2025-01-17 04:39:16 +00:00
|
|
|
}
|