1
0
Fork 0
mirror of synced 2024-10-02 10:16:27 +13:00

fix: add nested models to specifications

This commit is contained in:
Torsten Dittmann 2022-06-30 01:41:49 +02:00
parent 08704e8c93
commit 056e0d79ed
5 changed files with 173 additions and 244 deletions

View file

@ -123,105 +123,94 @@ $cli
], ],
]; ];
foreach (['swagger2', 'open-api3'] as $format) { foreach ($platforms as $platform) {
foreach ($platforms as $platform) { $routes = [];
$routes = []; $models = [];
$models = []; $services = [];
$services = [];
foreach ($appRoutes as $key => $method) { foreach ($appRoutes as $key => $method) {
foreach ($method as $route) { foreach ($method as $route) {
/** @var \Utopia\Route $route */ /** @var \Utopia\Route $route */
$routeSecurity = $route->getLabel('sdk.auth', []); $routeSecurity = $route->getLabel('sdk.auth', []);
$sdkPlatofrms = []; $sdkPlatofrms = [];
foreach ($routeSecurity as $value) { foreach ($routeSecurity as $value) {
switch ($value) { switch ($value) {
case APP_AUTH_TYPE_SESSION: case APP_AUTH_TYPE_SESSION:
$sdkPlatofrms[] = APP_PLATFORM_CLIENT; $sdkPlatofrms[] = APP_PLATFORM_CLIENT;
break; break;
case APP_AUTH_TYPE_KEY: case APP_AUTH_TYPE_KEY:
$sdkPlatofrms[] = APP_PLATFORM_SERVER; $sdkPlatofrms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_JWT: case APP_AUTH_TYPE_JWT:
$sdkPlatofrms[] = APP_PLATFORM_SERVER; $sdkPlatofrms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_ADMIN: case APP_AUTH_TYPE_ADMIN:
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE; $sdkPlatofrms[] = APP_PLATFORM_CONSOLE;
break; break;
}
} }
if (empty($routeSecurity)) {
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
}
if (!$route->getLabel('docs', true)) {
continue;
}
if ($route->getLabel('sdk.mock', false) && !$mocks) {
continue;
}
if (!$route->getLabel('sdk.mock', false) && $mocks) {
continue;
}
if (empty($route->getLabel('sdk.namespace', null))) {
continue;
}
if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatofrms)) {
continue;
}
$routes[] = $route;
$modelLabel = $route->getLabel('sdk.response.model', 'none');
\is_array($modelLabel) ? \array_map(function ($m) use ($response) {
return $response->getModel($m);
}, $modelLabel) : $response->getModel($modelLabel);
} }
}
foreach (Config::getParam('services', []) as $service) { if (empty($routeSecurity)) {
if ( $sdkPlatofrms[] = APP_PLATFORM_CLIENT;
!isset($service['docs']) // Skip service if not part of the public API }
|| !isset($service['sdk'])
|| !$service['docs'] if (!$route->getLabel('docs', true)) {
|| !$service['sdk']
) {
continue; continue;
} }
$services[] = [ if ($route->getLabel('sdk.mock', false) && !$mocks) {
'name' => $service['key'] ?? '', continue;
'description' => $service['subtitle'] ?? '',
'x-globalAttributes' => $service['globalAttributes'] ?? [],
];
}
$models = $response->getModels();
foreach ($models as $key => $value) {
if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
unset($models[$key]);
} }
if (!$route->getLabel('sdk.mock', false) && $mocks) {
continue;
}
if (empty($route->getLabel('sdk.namespace', null))) {
continue;
}
if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatofrms)) {
continue;
}
$routes[] = $route;
}
}
foreach (Config::getParam('services', []) as $service) {
if (
!isset($service['docs']) // Skip service if not part of the public API
|| !isset($service['sdk'])
|| !$service['docs']
|| !$service['sdk']
) {
continue;
} }
switch ($format) { $services[] = [
case 'swagger2': 'name' => $service['key'] ?? '',
$formatInstance = new Swagger2(new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0); 'description' => $service['subtitle'] ?? '',
break; 'x-globalAttributes' => $service['globalAttributes'] ?? [],
];
}
case 'open-api3': $models = $response->getModels();
$formatInstance = new OpenAPI3(new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
break;
default: foreach ($models as $key => $value) {
throw new Exception('Format not found: ' . $format); if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
break; unset($models[$key]);
} }
}
// var_dump($models);
$arguments = [new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0];
foreach (['swagger2', 'open-api3'] as $format) {
$formatInstance = match($format) {
'swagger2' => new Swagger2(...$arguments),
'open-api3' => new OpenAPI3(...$arguments),
default => throw new Exception('Format not found: ' . $format)
};
$specs = new Specification($formatInstance); $specs = new Specification($formatInstance);
$endpoint = App::getEnv('_APP_HOME', '[HOSTNAME]'); $endpoint = App::getEnv('_APP_HOME', '[HOSTNAME]');

View file

@ -8,40 +8,22 @@ use Appwrite\Utopia\Response\Model;
abstract class Format abstract class Format
{ {
/** protected App $app;
* @var App
*/
protected $app;
/**
* @var array
*/
protected $services;
/** /**
* @var Route[] * @var Route[]
*/ */
protected $routes; protected array $routes;
/** /**
* @var Model[] * @var Model[]
*/ */
protected $models; protected array $models;
/** protected array $services;
* @var array protected array $keys;
*/ protected int $authCount;
protected $keys; protected array $params = [
/**
* @var int
*/
protected $authCount;
/**
* @var array
*/
protected $params = [
'name' => '', 'name' => '',
'description' => '', 'description' => '',
'endpoint' => 'https://localhost', 'endpoint' => 'https://localhost',
@ -56,14 +38,6 @@ abstract class Format
'license.url' => '', 'license.url' => '',
]; ];
/**
* @param App $app
* @param array $services
* @param Route[] $routes
* @param Model[] $models
* @param array $keys
* @param int $authCount
*/
public function __construct(App $app, array $services, array $routes, array $models, array $keys, int $authCount) public function __construct(App $app, array $services, array $routes, array $models, array $keys, int $authCount)
{ {
$this->app = $app; $this->app = $app;
@ -121,10 +95,6 @@ abstract class Format
*/ */
public function getParam(string $key, string $default = ''): string public function getParam(string $key, string $default = ''): string
{ {
if (!isset($this->params[$key])) { return $this->params[$key] ?? $default;
return $default;
}
return $this->params[$key];
} }
} }

View file

@ -4,35 +4,40 @@ namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format; use Appwrite\Specification\Format;
use Appwrite\Template\Template; use Appwrite\Template\Template;
use Appwrite\Utopia\Response\Model;
use Utopia\Validator; use Utopia\Validator;
class OpenAPI3 extends Format class OpenAPI3 extends Format
{ {
/**
* Get Name.
*
* Get format name
*
* @return string
*/
public function getName(): string public function getName(): string
{ {
return 'Open API 3'; return 'Open API 3';
} }
/** protected function getNestedModels(Model $model, array &$usedModels): void
* Parse {
* foreach ($model->getRules() as $rule) {
* Parses Appwrite App to given format if (
* in_array($model->getType(), $usedModels)
* @return array && !in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])
*/ ) {
$usedModels[] = $rule['type'];
foreach ($this->models as $m) {
if ($m->getType() === $rule['type']) {
$this->getNestedModels($m, $usedModels);
return;
}
}
}
}
}
public function parse(): array public function parse(): array
{ {
/** /**
* Specifications (v3.0.0): * Specifications (v3.0.0):
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
*/ */
$output = [ $output = [
'openapi' => '3.0.0', 'openapi' => '3.0.0',
'info' => [ 'info' => [
@ -89,7 +94,7 @@ class OpenAPI3 extends Format
$usedModels = []; $usedModels = [];
foreach ($this->routes as $route) { /** @var \Utopia\Route $route */ foreach ($this->routes as $route) {
$url = \str_replace('/v1', '', $route->getPath()); $url = \str_replace('/v1', '', $route->getPath());
$scope = $route->getLabel('scope', ''); $scope = $route->getLabel('scope', '');
$hide = $route->getLabel('sdk.hide', false); $hide = $route->getLabel('sdk.hide', false);
@ -104,34 +109,32 @@ class OpenAPI3 extends Format
$produces = $route->getLabel('sdk.response.type', null); $produces = $route->getLabel('sdk.response.type', null);
$model = $route->getLabel('sdk.response.model', 'none'); $model = $route->getLabel('sdk.response.model', 'none');
$routeSecurity = $route->getLabel('sdk.auth', []); $routeSecurity = $route->getLabel('sdk.auth', []);
$sdkPlatofrms = []; $sdkPlatforms = [];
foreach ($routeSecurity as $value) { foreach ($routeSecurity as $value) {
switch ($value) { switch ($value) {
case APP_AUTH_TYPE_SESSION: case APP_AUTH_TYPE_SESSION:
$sdkPlatofrms[] = APP_PLATFORM_CLIENT; $sdkPlatforms[] = APP_PLATFORM_CLIENT;
break; break;
case APP_AUTH_TYPE_KEY: case APP_AUTH_TYPE_KEY:
$sdkPlatofrms[] = APP_PLATFORM_SERVER; $sdkPlatforms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_JWT: case APP_AUTH_TYPE_JWT:
$sdkPlatofrms[] = APP_PLATFORM_SERVER; $sdkPlatforms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_ADMIN: case APP_AUTH_TYPE_ADMIN:
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE; $sdkPlatforms[] = APP_PLATFORM_CONSOLE;
break; break;
} }
} }
if (empty($routeSecurity)) { if (empty($routeSecurity)) {
$sdkPlatofrms[] = APP_PLATFORM_CLIENT; $sdkPlatforms[] = APP_PLATFORM_CLIENT;
} }
$temp = [ $temp = [
'summary' => $route->getDesc(), 'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id), 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($id),
// 'consumes' => [],
// 'produces' => [$produces],
'tags' => [$route->getLabel('sdk.namespace', 'default')], 'tags' => [$route->getLabel('sdk.namespace', 'default')],
'description' => ($desc) ? \file_get_contents($desc) : '', 'description' => ($desc) ? \file_get_contents($desc) : '',
'responses' => [], 'responses' => [],
@ -146,20 +149,14 @@ class OpenAPI3 extends Format
'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-time' => $route->getLabel('abuse-time', 3600),
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
'scope' => $route->getLabel('scope', ''), 'scope' => $route->getLabel('scope', ''),
'platforms' => $sdkPlatofrms, 'platforms' => $sdkPlatforms,
'packaging' => $route->getLabel('sdk.packaging', false), 'packaging' => $route->getLabel('sdk.packaging', false),
], ],
]; ];
foreach ($this->models as $key => $value) { foreach ($this->models as $value) {
if (\is_array($model)) { if (\is_array($model)) {
$model = \array_map(function ($m) use ($value) { $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model);
if ($m === $value->getType()) {
return $value;
}
return $m;
}, $model);
} else { } else {
if ($value->getType() === $model) { if ($value->getType() === $model) {
$model = $value; $model = $value;
@ -168,9 +165,9 @@ class OpenAPI3 extends Format
} }
} }
if (!(\is_array($model)) && $model->isNone()) { if (!(\is_array($model)) && $model->isNone()) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => (in_array($produces, [ 'description' => in_array($produces, [
'image/*', 'image/*',
'image/jpeg', 'image/jpeg',
'image/gif', 'image/gif',
@ -179,16 +176,11 @@ class OpenAPI3 extends Format
'image/svg-x', 'image/svg-x',
'image/x-icon', 'image/x-icon',
'image/bmp', 'image/bmp',
])) ? 'Image' : 'File', ]) ? 'Image' : 'File',
// 'schema' => [
// 'type' => 'file'
// ],
]; ];
} else { } else {
if (\is_array($model)) { if (\is_array($model)) {
$modelDescription = \join(', or ', \array_map(function ($m) { $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model));
return $m->getName();
}, $model));
// model has multiple possible responses, we will use oneOf // model has multiple possible responses, we will use oneOf
foreach ($model as $m) { foreach ($model as $m) {
@ -200,9 +192,7 @@ class OpenAPI3 extends Format
'content' => [ 'content' => [
$produces => [ $produces => [
'schema' => [ 'schema' => [
'oneOf' => \array_map(function ($m) { 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model)
return ['$ref' => '#/components/schemas/' . $m->getType()];
}, $model)
], ],
], ],
], ],
@ -255,7 +245,10 @@ class OpenAPI3 extends Format
$bodyRequired = []; $bodyRequired = [];
foreach ($route->getParams() as $name => $param) { // Set params foreach ($route->getParams() as $name => $param) { // Set params
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator']; /* @var $validator \Utopia\Validator */ /**
* @var \Utopia\Validator $validator
*/
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
$node = [ $node = [
'name' => $name, 'name' => $name,
@ -329,7 +322,8 @@ class OpenAPI3 extends Format
$node['schema']['format'] = 'password'; $node['schema']['format'] = 'password';
$node['schema']['x-example'] = 'password'; $node['schema']['x-example'] = 'password';
break; break;
case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */ case 'Utopia\Validator\Range':
/** @var \Utopia\Validator\Range $validator */
$node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType(); $node['schema']['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();
$node['schema']['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float'; $node['schema']['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float';
$node['schema']['x-example'] = $validator->getMin(); $node['schema']['x-example'] = $validator->getMin();
@ -351,7 +345,8 @@ class OpenAPI3 extends Format
$node['schema']['format'] = 'url'; $node['schema']['format'] = 'url';
$node['schema']['x-example'] = 'https://example.com'; $node['schema']['x-example'] = 'https://example.com';
break; break;
case 'Utopia\Validator\WhiteList': /** @var \Utopia\Validator\WhiteList $validator */ case 'Utopia\Validator\WhiteList':
/** @var \Utopia\Validator\WhiteList $validator */
$node['schema']['type'] = $validator->getType(); $node['schema']['type'] = $validator->getType();
$node['schema']['x-example'] = $validator->getList()[0]; $node['schema']['x-example'] = $validator->getList()[0];
@ -413,20 +408,11 @@ class OpenAPI3 extends Format
$temp['requestBody'] = $body; $temp['requestBody'] = $body;
} }
//$temp['consumes'] = $consumes;
$output['paths'][$url][\strtolower($route->getMethod())] = $temp; $output['paths'][$url][\strtolower($route->getMethod())] = $temp;
} }
foreach ($this->models as $model) { foreach ($this->models as $model) {
foreach ($model->getRules() as $rule) { $this->getNestedModels($model, $usedModels);
if (
in_array($model->getType(), $usedModels)
&& !in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])
) {
$usedModels[] = $rule['type'];
}
}
} }
foreach ($this->models as $model) { foreach ($this->models as $model) {

View file

@ -4,34 +4,39 @@ namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format; use Appwrite\Specification\Format;
use Appwrite\Template\Template; use Appwrite\Template\Template;
use Appwrite\Utopia\Response\Model;
use Utopia\Validator; use Utopia\Validator;
class Swagger2 extends Format class Swagger2 extends Format
{ {
/**
* Get Name.
*
* Get format name
*
* @return string
*/
public function getName(): string public function getName(): string
{ {
return 'Swagger 2'; return 'Swagger 2';
} }
/** protected function getNestedModels(Model $model, array &$usedModels): void
* Parse {
* foreach ($model->getRules() as $rule) {
* Parses Appwrite App to given format if (
* in_array($model->getType(), $usedModels)
* @return array && !in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])
*/ ) {
$usedModels[] = $rule['type'];
foreach ($this->models as $m) {
if ($m->getType() === $rule['type']) {
$this->getNestedModels($m, $usedModels);
return;
}
}
}
}
}
public function parse(): array public function parse(): array
{ {
/* /*
* Specifications (v3.0.0): * Specifications (v2.0):
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md * https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md
*/ */
$output = [ $output = [
'swagger' => '2.0', 'swagger' => '2.0',
@ -87,7 +92,8 @@ class Swagger2 extends Format
$usedModels = []; $usedModels = [];
foreach ($this->routes as $route) { /** @var \Utopia\Route $route */ foreach ($this->routes as $route) {
/** @var \Utopia\Route $route */
$url = \str_replace('/v1', '', $route->getPath()); $url = \str_replace('/v1', '', $route->getPath());
$scope = $route->getLabel('scope', ''); $scope = $route->getLabel('scope', '');
$hide = $route->getLabel('sdk.hide', false); $hide = $route->getLabel('sdk.hide', false);
@ -102,27 +108,27 @@ class Swagger2 extends Format
$produces = $route->getLabel('sdk.response.type', null); $produces = $route->getLabel('sdk.response.type', null);
$model = $route->getLabel('sdk.response.model', 'none'); $model = $route->getLabel('sdk.response.model', 'none');
$routeSecurity = $route->getLabel('sdk.auth', []); $routeSecurity = $route->getLabel('sdk.auth', []);
$sdkPlatofrms = []; $sdkPlatforms = [];
foreach ($routeSecurity as $value) { foreach ($routeSecurity as $value) {
switch ($value) { switch ($value) {
case APP_AUTH_TYPE_SESSION: case APP_AUTH_TYPE_SESSION:
$sdkPlatofrms[] = APP_PLATFORM_CLIENT; $sdkPlatforms[] = APP_PLATFORM_CLIENT;
break; break;
case APP_AUTH_TYPE_KEY: case APP_AUTH_TYPE_KEY:
$sdkPlatofrms[] = APP_PLATFORM_SERVER; $sdkPlatforms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_JWT: case APP_AUTH_TYPE_JWT:
$sdkPlatofrms[] = APP_PLATFORM_SERVER; $sdkPlatforms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_ADMIN: case APP_AUTH_TYPE_ADMIN:
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE; $sdkPlatforms[] = APP_PLATFORM_CONSOLE;
break; break;
} }
} }
if (empty($routeSecurity)) { if (empty($routeSecurity)) {
$sdkPlatofrms[] = APP_PLATFORM_CLIENT; $sdkPlatforms[] = APP_PLATFORM_CLIENT;
} }
$temp = [ $temp = [
@ -144,7 +150,7 @@ class Swagger2 extends Format
'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-time' => $route->getLabel('abuse-time', 3600),
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
'scope' => $route->getLabel('scope', ''), 'scope' => $route->getLabel('scope', ''),
'platforms' => $sdkPlatofrms, 'platforms' => $sdkPlatforms,
'packaging' => $route->getLabel('sdk.packaging', false), 'packaging' => $route->getLabel('sdk.packaging', false),
], ],
]; ];
@ -153,14 +159,9 @@ class Swagger2 extends Format
$temp['produces'][] = $produces; $temp['produces'][] = $produces;
} }
foreach ($this->models as $key => $value) { foreach ($this->models as $value) {
if (\is_array($model)) { if (\is_array($model)) {
$model = \array_map(function ($m) use ($value) { $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model);
if ($m === $value->getType()) {
return $value;
}
return $m;
}, $model);
} else { } else {
if ($value->getType() === $model) { if ($value->getType() === $model) {
$model = $value; $model = $value;
@ -171,7 +172,7 @@ class Swagger2 extends Format
if (!(\is_array($model)) && $model->isNone()) { if (!(\is_array($model)) && $model->isNone()) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => (in_array($produces, [ 'description' => in_array($produces, [
'image/*', 'image/*',
'image/jpeg', 'image/jpeg',
'image/gif', 'image/gif',
@ -180,16 +181,14 @@ class Swagger2 extends Format
'image/svg-x', 'image/svg-x',
'image/x-icon', 'image/x-icon',
'image/bmp', 'image/bmp',
])) ? 'Image' : 'File', ]) ? 'Image' : 'File',
'schema' => [ 'schema' => [
'type' => 'file' 'type' => 'file'
], ],
]; ];
} else { } else {
if (\is_array($model)) { if (\is_array($model)) {
$modelDescription = \join(', or ', \array_map(function ($m) { $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model));
return $m->getName();
}, $model));
// model has multiple possible responses, we will use oneOf // model has multiple possible responses, we will use oneOf
foreach ($model as $m) { foreach ($model as $m) {
$usedModels[] = $m->getType(); $usedModels[] = $m->getType();
@ -244,7 +243,8 @@ class Swagger2 extends Format
$bodyRequired = []; $bodyRequired = [];
foreach ($route->getParams() as $name => $param) { // Set params foreach ($route->getParams() as $name => $param) { // Set params
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator']; /** @var \Utopia\Validator $validator */ /** @var \Utopia\Validator $validator */
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
$node = [ $node = [
'name' => $name, 'name' => $name,
@ -294,7 +294,6 @@ class Swagger2 extends Format
$node['type'] = 'object'; $node['type'] = 'object';
$node['default'] = (empty($param['default'])) ? new \stdClass() : $param['default']; $node['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
$node['x-example'] = '{}'; $node['x-example'] = '{}';
//$node['format'] = 'json';
break; break;
case 'Utopia\Storage\Validator\File': case 'Utopia\Storage\Validator\File':
$consumes = ['multipart/form-data']; $consumes = ['multipart/form-data'];
@ -320,7 +319,8 @@ class Swagger2 extends Format
$node['format'] = 'password'; $node['format'] = 'password';
$node['x-example'] = 'password'; $node['x-example'] = 'password';
break; break;
case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */ case 'Utopia\Validator\Range':
/** @var \Utopia\Validator\Range $validator */
$node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType(); $node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();
$node['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float'; $node['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float';
$node['x-example'] = $validator->getMin(); $node['x-example'] = $validator->getMin();
@ -342,7 +342,8 @@ class Swagger2 extends Format
$node['format'] = 'url'; $node['format'] = 'url';
$node['x-example'] = 'https://example.com'; $node['x-example'] = 'https://example.com';
break; break;
case 'Utopia\Validator\WhiteList': /** @var \Utopia\Validator\WhiteList $validator */ case 'Utopia\Validator\WhiteList':
/** @var \Utopia\Validator\WhiteList $validator */
$node['type'] = $validator->getType(); $node['type'] = $validator->getType();
$node['x-example'] = $validator->getList()[0]; $node['x-example'] = $validator->getList()[0];
@ -410,14 +411,7 @@ class Swagger2 extends Format
} }
foreach ($this->models as $model) { foreach ($this->models as $model) {
foreach ($model->getRules() as $rule) { $this->getNestedModels($model, $usedModels);
if (
in_array($model->getType(), $usedModels)
&& !in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])
) {
$usedModels[] = $rule['type'];
}
}
} }
foreach ($this->models as $model) { foreach ($this->models as $model) {
@ -485,15 +479,11 @@ class Swagger2 extends Format
if (\is_array($rule['type'])) { if (\is_array($rule['type'])) {
if ($rule['array']) { if ($rule['array']) {
$items = [ $items = [
'x-anyOf' => \array_map(function ($type) { 'x-anyOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type'])
return ['$ref' => '#/definitions/' . $type];
}, $rule['type'])
]; ];
} else { } else {
$items = [ $items = [
'x-oneOf' => \array_map(function ($type) { 'x-oneOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type'])
return ['$ref' => '#/definitions/' . $type];
}, $rule['type'])
]; ];
} }
} else { } else {

View file

@ -4,14 +4,8 @@ namespace Appwrite\Specification;
class Specification class Specification
{ {
/** protected Format $format;
* @var Format
*/
protected $format;
/**
* @param Format $format
*/
public function __construct(Format $format) public function __construct(Format $format)
{ {
$this->format = $format; $this->format = $format;