Added spec generator CLI command, remove old HTTP endpoint
This commit is contained in:
parent
18a2e020c2
commit
d1b5f310e3
|
@ -259,6 +259,7 @@ RUN chmod +x /usr/local/bin/doctor && \
|
||||||
chmod +x /usr/local/bin/realtime && \
|
chmod +x /usr/local/bin/realtime && \
|
||||||
chmod +x /usr/local/bin/schedule && \
|
chmod +x /usr/local/bin/schedule && \
|
||||||
chmod +x /usr/local/bin/sdks && \
|
chmod +x /usr/local/bin/sdks && \
|
||||||
|
chmod +x /usr/local/bin/specs && \
|
||||||
chmod +x /usr/local/bin/ssl && \
|
chmod +x /usr/local/bin/ssl && \
|
||||||
chmod +x /usr/local/bin/test && \
|
chmod +x /usr/local/bin/test && \
|
||||||
chmod +x /usr/local/bin/vars && \
|
chmod +x /usr/local/bin/vars && \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once __DIR__.'/init.php';
|
require_once __DIR__.'/init.php';
|
||||||
|
require_once __DIR__.'/controllers/general.php';
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\CLI\CLI;
|
use Utopia\CLI\CLI;
|
||||||
|
@ -13,6 +13,7 @@ include 'tasks/maintenance.php';
|
||||||
include 'tasks/install.php';
|
include 'tasks/install.php';
|
||||||
include 'tasks/migrate.php';
|
include 'tasks/migrate.php';
|
||||||
include 'tasks/sdks.php';
|
include 'tasks/sdks.php';
|
||||||
|
include 'tasks/specs.php';
|
||||||
include 'tasks/ssl.php';
|
include 'tasks/ssl.php';
|
||||||
include 'tasks/vars.php';
|
include 'tasks/vars.php';
|
||||||
include 'tasks/usage.php';
|
include 'tasks/usage.php';
|
||||||
|
|
1
app/config/specs/open-api3-0.12.x-client.json
Normal file
1
app/config/specs/open-api3-0.12.x-client.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-0.12.x-console.json
Normal file
1
app/config/specs/open-api3-0.12.x-console.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-0.12.x-server.json
Normal file
1
app/config/specs/open-api3-0.12.x-server.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-latest-client.json
Normal file
1
app/config/specs/open-api3-latest-client.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-latest-console.json
Normal file
1
app/config/specs/open-api3-latest-console.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-latest-server.json
Normal file
1
app/config/specs/open-api3-latest-server.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-tests-client.json
Normal file
1
app/config/specs/open-api3-tests-client.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-tests-console.json
Normal file
1
app/config/specs/open-api3-tests-console.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/open-api3-tests-server.json
Normal file
1
app/config/specs/open-api3-tests-server.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-0.12.x-client.json
Normal file
1
app/config/specs/swagger2-0.12.x-client.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-0.12.x-console.json
Normal file
1
app/config/specs/swagger2-0.12.x-console.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-0.12.x-server.json
Normal file
1
app/config/specs/swagger2-0.12.x-server.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-latest-client.json
Normal file
1
app/config/specs/swagger2-latest-client.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-latest-console.json
Normal file
1
app/config/specs/swagger2-latest-console.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-latest-server.json
Normal file
1
app/config/specs/swagger2-latest-server.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-tests-client.json
Normal file
1
app/config/specs/swagger2-tests-client.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-tests-console.json
Normal file
1
app/config/specs/swagger2-tests-console.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/specs/swagger2-tests-server.json
Normal file
1
app/config/specs/swagger2-tests-server.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -245,232 +245,6 @@ App::get('/error/:code')
|
||||||
->setParam('body', $page);
|
->setParam('body', $page);
|
||||||
});
|
});
|
||||||
|
|
||||||
App::get('/specs/:format')
|
|
||||||
->groups(['web', 'home'])
|
|
||||||
->label('scope', 'public')
|
|
||||||
->label('docs', false)
|
|
||||||
->label('origin', '*')
|
|
||||||
->param('format', 'swagger2', new WhiteList(['swagger2', 'open-api3'], true), 'Spec format.', true)
|
|
||||||
->param('platform', APP_PLATFORM_CLIENT, new WhiteList([APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER, APP_PLATFORM_CONSOLE], true), 'Choose target platform.', true)
|
|
||||||
->param('tests', 0, function () {return new Range(0, 1);}, 'Include only test services.', true)
|
|
||||||
->inject('utopia')
|
|
||||||
->inject('request')
|
|
||||||
->inject('response')
|
|
||||||
->action(function ($format, $platform, $tests, $utopia, $request, $response) {
|
|
||||||
/** @var Utopia\App $utopia */
|
|
||||||
/** @var Utopia\Swoole\Request $request */
|
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
|
||||||
|
|
||||||
$platforms = [
|
|
||||||
'client' => APP_PLATFORM_CLIENT,
|
|
||||||
'server' => APP_PLATFORM_SERVER,
|
|
||||||
'console' => APP_PLATFORM_CONSOLE,
|
|
||||||
];
|
|
||||||
|
|
||||||
$authCounts = [
|
|
||||||
'client' => 1,
|
|
||||||
'server' => 2,
|
|
||||||
'console' => 1,
|
|
||||||
];
|
|
||||||
|
|
||||||
$routes = [];
|
|
||||||
$models = [];
|
|
||||||
$services = [];
|
|
||||||
|
|
||||||
$keys = [
|
|
||||||
APP_PLATFORM_CLIENT => [
|
|
||||||
'Project' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Project',
|
|
||||||
'description' => 'Your project ID',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'JWT' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-JWT',
|
|
||||||
'description' => 'Your secret JSON Web Token',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'Locale' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Locale',
|
|
||||||
'description' => '',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
APP_PLATFORM_SERVER => [
|
|
||||||
'Project' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Project',
|
|
||||||
'description' => 'Your project ID',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'Key' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Key',
|
|
||||||
'description' => 'Your secret API key',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'JWT' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-JWT',
|
|
||||||
'description' => 'Your secret JSON Web Token',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'Locale' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Locale',
|
|
||||||
'description' => '',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
APP_PLATFORM_CONSOLE => [
|
|
||||||
'Project' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Project',
|
|
||||||
'description' => 'Your project ID',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'Key' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Key',
|
|
||||||
'description' => 'Your secret API key',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'JWT' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-JWT',
|
|
||||||
'description' => 'Your secret JSON Web Token',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'Locale' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Locale',
|
|
||||||
'description' => '',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
'Mode' => [
|
|
||||||
'type' => 'apiKey',
|
|
||||||
'name' => 'X-Appwrite-Mode',
|
|
||||||
'description' => '',
|
|
||||||
'in' => 'header',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($utopia->getRoutes() as $key => $method) {
|
|
||||||
foreach ($method as $route) { /** @var \Utopia\Route $route */
|
|
||||||
$routeSecurity = $route->getLabel('sdk.auth', []);
|
|
||||||
$sdkPlatofrms = [];
|
|
||||||
|
|
||||||
foreach ($routeSecurity as $value) {
|
|
||||||
switch ($value) {
|
|
||||||
case APP_AUTH_TYPE_SESSION:
|
|
||||||
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
|
||||||
break;
|
|
||||||
case APP_AUTH_TYPE_KEY:
|
|
||||||
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
|
||||||
break;
|
|
||||||
case APP_AUTH_TYPE_JWT:
|
|
||||||
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
|
||||||
break;
|
|
||||||
case APP_AUTH_TYPE_ADMIN:
|
|
||||||
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(empty($routeSecurity)) {
|
|
||||||
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$route->getLabel('docs', true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($route->getLabel('sdk.mock', false) && !$tests) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$route->getLabel('sdk.mock', false) && $tests) {
|
|
||||||
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');
|
|
||||||
$model = \is_array($modelLabel) ? \array_map(function($m) use($response) {
|
|
||||||
return $response->getModel($m);
|
|
||||||
}, $modelLabel) : $response->getModel($modelLabel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$services[] = [
|
|
||||||
'name' => $service['key'] ?? '',
|
|
||||||
'description' => $service['subtitle'] ?? '',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$models = $response->getModels();
|
|
||||||
|
|
||||||
foreach ($models as $key => $value) {
|
|
||||||
if($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
|
|
||||||
unset($models[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($format) {
|
|
||||||
case 'swagger2':
|
|
||||||
$format = new Swagger2($utopia, $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'open-api3':
|
|
||||||
$format = new OpenAPI3($utopia, $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Exception('Format not found', 404);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$specs = new Specification($format);
|
|
||||||
|
|
||||||
$format
|
|
||||||
->setParam('name', APP_NAME)
|
|
||||||
->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)')
|
|
||||||
->setParam('endpoint', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/v1')
|
|
||||||
->setParam('version', APP_VERSION_STABLE)
|
|
||||||
->setParam('terms', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/policy/terms')
|
|
||||||
->setParam('support.email', App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM))
|
|
||||||
->setParam('support.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/support')
|
|
||||||
->setParam('contact.name', APP_NAME.' Team')
|
|
||||||
->setParam('contact.email', App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM))
|
|
||||||
->setParam('contact.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/support')
|
|
||||||
->setParam('license.name', 'BSD-3-Clause')
|
|
||||||
->setParam('license.url', 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE')
|
|
||||||
->setParam('docs.description', 'Full API docs, specs and tutorials')
|
|
||||||
->setParam('docs.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/docs')
|
|
||||||
;
|
|
||||||
|
|
||||||
$response
|
|
||||||
->json($specs->parse());
|
|
||||||
});
|
|
||||||
|
|
||||||
App::get('/versions')
|
App::get('/versions')
|
||||||
->desc('Get Version')
|
->desc('Get Version')
|
||||||
->groups(['web', 'home'])
|
->groups(['web', 'home'])
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
global $cli;
|
global $cli;
|
||||||
|
|
||||||
require_once __DIR__.'/../init.php';
|
|
||||||
|
|
||||||
use Appwrite\Event\Event;
|
use Appwrite\Event\Event;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
|
|
271
app/tasks/specs.php
Normal file
271
app/tasks/specs.php
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
global $cli;
|
||||||
|
|
||||||
|
use Utopia\Validator\Text;
|
||||||
|
use Appwrite\Specification\Format\OpenAPI3;
|
||||||
|
use Appwrite\Specification\Format\Swagger2;
|
||||||
|
use Appwrite\Specification\Specification;
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
|
use Swoole\Http\Response as HttpResponse;
|
||||||
|
use Utopia\App;
|
||||||
|
use Utopia\CLI\Console;
|
||||||
|
use Utopia\Config\Config;
|
||||||
|
use Utopia\Request;
|
||||||
|
use Utopia\Validator\WhiteList;
|
||||||
|
|
||||||
|
$cli
|
||||||
|
->task('specs')
|
||||||
|
->param('version', 'latest', new Text(8), 'Spec version', true)
|
||||||
|
->param('mode', 'normal', new WhiteList(['normal', 'tests']), 'Spec Mode', true)
|
||||||
|
->action(function ($version, $mode) use ($register) {
|
||||||
|
$db = $register->get('db');
|
||||||
|
$redis = $register->get('cache');
|
||||||
|
$appRoutes = App::getRoutes();
|
||||||
|
$response = new Response(new HttpResponse());
|
||||||
|
$tests = ($mode === 'tests');
|
||||||
|
|
||||||
|
App::setResource('request', function() {
|
||||||
|
return new Request;
|
||||||
|
});
|
||||||
|
|
||||||
|
App::setResource('response', function() use ($response) {
|
||||||
|
return $response;
|
||||||
|
});
|
||||||
|
|
||||||
|
App::setResource('db', fn() => $db);
|
||||||
|
App::setResource('cache', fn() => $redis);
|
||||||
|
|
||||||
|
$platforms = [
|
||||||
|
'client' => APP_PLATFORM_CLIENT,
|
||||||
|
'server' => APP_PLATFORM_SERVER,
|
||||||
|
'console' => APP_PLATFORM_CONSOLE,
|
||||||
|
];
|
||||||
|
|
||||||
|
$authCounts = [
|
||||||
|
'client' => 1,
|
||||||
|
'server' => 2,
|
||||||
|
'console' => 1,
|
||||||
|
];
|
||||||
|
|
||||||
|
$keys = [
|
||||||
|
APP_PLATFORM_CLIENT => [
|
||||||
|
'Project' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Project',
|
||||||
|
'description' => 'Your project ID',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'JWT' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-JWT',
|
||||||
|
'description' => 'Your secret JSON Web Token',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'Locale' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Locale',
|
||||||
|
'description' => '',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
APP_PLATFORM_SERVER => [
|
||||||
|
'Project' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Project',
|
||||||
|
'description' => 'Your project ID',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'Key' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Key',
|
||||||
|
'description' => 'Your secret API key',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'JWT' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-JWT',
|
||||||
|
'description' => 'Your secret JSON Web Token',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'Locale' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Locale',
|
||||||
|
'description' => '',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
APP_PLATFORM_CONSOLE => [
|
||||||
|
'Project' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Project',
|
||||||
|
'description' => 'Your project ID',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'Key' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Key',
|
||||||
|
'description' => 'Your secret API key',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'JWT' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-JWT',
|
||||||
|
'description' => 'Your secret JSON Web Token',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'Locale' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Locale',
|
||||||
|
'description' => '',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
'Mode' => [
|
||||||
|
'type' => 'apiKey',
|
||||||
|
'name' => 'X-Appwrite-Mode',
|
||||||
|
'description' => '',
|
||||||
|
'in' => 'header',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach (['swagger2', 'open-api3'] as $format) {
|
||||||
|
foreach ($platforms as $platform) {
|
||||||
|
|
||||||
|
$routes = [];
|
||||||
|
$models = [];
|
||||||
|
$services = [];
|
||||||
|
|
||||||
|
foreach ($appRoutes as $key => $method) {
|
||||||
|
foreach ($method as $route) { /** @var \Utopia\Route $route */
|
||||||
|
$routeSecurity = $route->getLabel('sdk.auth', []);
|
||||||
|
$sdkPlatofrms = [];
|
||||||
|
|
||||||
|
foreach ($routeSecurity as $value) {
|
||||||
|
switch ($value) {
|
||||||
|
case APP_AUTH_TYPE_SESSION:
|
||||||
|
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
||||||
|
break;
|
||||||
|
case APP_AUTH_TYPE_KEY:
|
||||||
|
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
||||||
|
break;
|
||||||
|
case APP_AUTH_TYPE_JWT:
|
||||||
|
$sdkPlatofrms[] = APP_PLATFORM_SERVER;
|
||||||
|
break;
|
||||||
|
case APP_AUTH_TYPE_ADMIN:
|
||||||
|
$sdkPlatofrms[] = APP_PLATFORM_CONSOLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($routeSecurity)) {
|
||||||
|
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$route->getLabel('docs', true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($route->getLabel('sdk.mock', false) && !$tests) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$route->getLabel('sdk.mock', false) && $tests) {
|
||||||
|
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');
|
||||||
|
$model = \is_array($modelLabel) ? \array_map(function($m) use($response) {
|
||||||
|
return $response->getModel($m);
|
||||||
|
}, $modelLabel) : $response->getModel($modelLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
$services[] = [
|
||||||
|
'name' => $service['key'] ?? '',
|
||||||
|
'description' => $service['subtitle'] ?? '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$models = $response->getModels();
|
||||||
|
|
||||||
|
foreach ($models as $key => $value) {
|
||||||
|
if($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
|
||||||
|
unset($models[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($format) {
|
||||||
|
case 'swagger2':
|
||||||
|
$formatInstance = new Swagger2(new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'open-api3':
|
||||||
|
$formatInstance = new OpenAPI3(new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception('Format not found: '.$format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$specs = new Specification($formatInstance);
|
||||||
|
$endpoint = App::getEnv('_APP_HOME', '[HOSTNAME]');
|
||||||
|
$email = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
|
||||||
|
|
||||||
|
$formatInstance
|
||||||
|
->setParam('name', APP_NAME)
|
||||||
|
->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)')
|
||||||
|
->setParam('endpoint', 'https://HOSTNAME/v1')
|
||||||
|
->setParam('version', APP_VERSION_STABLE)
|
||||||
|
->setParam('terms', $endpoint.'/policy/terms')
|
||||||
|
->setParam('support.email', $email)
|
||||||
|
->setParam('support.url', $endpoint.'/support')
|
||||||
|
->setParam('contact.name', APP_NAME.' Team')
|
||||||
|
->setParam('contact.email', $email)
|
||||||
|
->setParam('contact.url', $endpoint.'/support')
|
||||||
|
->setParam('license.name', 'BSD-3-Clause')
|
||||||
|
->setParam('license.url', 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE')
|
||||||
|
->setParam('docs.description', 'Full API docs, specs and tutorials')
|
||||||
|
->setParam('docs.url', $endpoint.'/docs')
|
||||||
|
;
|
||||||
|
|
||||||
|
if($tests) {
|
||||||
|
$path = __DIR__.'/../config/specs/'.$format.'-tests-'.$platform.'.json';
|
||||||
|
|
||||||
|
if(!file_put_contents($path, json_encode($specs->parse()))) {
|
||||||
|
throw new Exception('Failed to save tests spec file: '.$path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::success('Saved tests spec file: ' . realpath($path));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = __DIR__.'/../config/specs/'.$format.'-'.$version.'-'.$platform.'.json';
|
||||||
|
|
||||||
|
if(!file_put_contents($path, json_encode($specs->parse()))) {
|
||||||
|
throw new Exception('Failed to save spec file: '.$path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::success('Saved spec file: ' . realpath($path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
global $cli, $register;
|
global $cli, $register;
|
||||||
|
|
||||||
require_once __DIR__ . '/../init.php';
|
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Cache\Adapter\Redis;
|
use Utopia\Cache\Adapter\Redis;
|
||||||
use Utopia\Cache\Cache;
|
use Utopia\Cache\Cache;
|
||||||
|
|
|
@ -396,7 +396,14 @@ class OpenAPI3 extends Format
|
||||||
foreach ($this->models as $model) {
|
foreach ($this->models as $model) {
|
||||||
foreach ($model->getRules() as $rule) {
|
foreach ($model->getRules() as $rule) {
|
||||||
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
|
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
|
||||||
$usedModels[] = $rule['type'];
|
if(\is_array($rule['type'])) {
|
||||||
|
foreach ($rule['type'] as $key => $value) {
|
||||||
|
$usedModels[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$usedModels[] = $rule['type'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,7 +393,14 @@ class Swagger2 extends Format
|
||||||
foreach ($this->models as $model) {
|
foreach ($this->models as $model) {
|
||||||
foreach ($model->getRules() as $rule) {
|
foreach ($model->getRules() as $rule) {
|
||||||
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
|
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
|
||||||
$usedModels[] = $rule['type'];
|
if(\is_array($rule['type'])) {
|
||||||
|
foreach ($rule['type'] as $key => $value) {
|
||||||
|
$usedModels[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$usedModels[] = $rule['type'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,13 +467,13 @@ class Swagger2 extends Format
|
||||||
if(\is_array($rule['type'])) {
|
if(\is_array($rule['type'])) {
|
||||||
if($rule['array']) {
|
if($rule['array']) {
|
||||||
$items = [
|
$items = [
|
||||||
'anyOf' => \array_map(function($type) {
|
'x-anyOf' => \array_map(function($type) {
|
||||||
return ['$ref' => '#/definitions/'.$type];
|
return ['$ref' => '#/definitions/'.$type];
|
||||||
}, $rule['type'])
|
}, $rule['type'])
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
$items = [
|
$items = [
|
||||||
'oneOf' => \array_map(function($type) {
|
'x-oneOf' => \array_map(function($type) {
|
||||||
return ['$ref' => '#/definitions/'.$type];
|
return ['$ref' => '#/definitions/'.$type];
|
||||||
}, $rule['type'])
|
}, $rule['type'])
|
||||||
];
|
];
|
||||||
|
@ -514,7 +521,7 @@ class Swagger2 extends Format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!in_array($name, $required)) {
|
if (!in_array($name, $required)) {
|
||||||
$output['definitions'][$model->getType()]['properties'][$name]['nullable'] = true;
|
$output['definitions'][$model->getType()]['properties'][$name]['x-nullable'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,26 +128,34 @@ class HTTPTest extends Scope
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
], []);
|
], []);
|
||||||
|
|
||||||
if(!file_put_contents(__DIR__ . '/../../resources/open-api3.json', json_encode($response['body']))) {
|
$directory = __DIR__ . '/../../../app/config/specs/';
|
||||||
throw new Exception('Failed to save spec file');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$files = scandir($directory);
|
||||||
$client = new Client();
|
$client = new Client();
|
||||||
$client->setEndpoint('https://validator.swagger.io');
|
$client->setEndpoint('https://validator.swagger.io');
|
||||||
|
|
||||||
/**
|
foreach($files as $file) {
|
||||||
* Test for SUCCESS
|
if(in_array($file, ['.', '..'])) {
|
||||||
*/
|
continue;
|
||||||
$response = $client->call(Client::METHOD_POST, '/validator/debug', [
|
}
|
||||||
'content-type' => 'application/json',
|
|
||||||
], json_decode(file_get_contents(realpath(__DIR__ . '/../../resources/open-api3.json')), true));
|
|
||||||
|
|
||||||
$response['body'] = json_decode($response['body'], true);
|
/**
|
||||||
|
* Test for SUCCESS
|
||||||
|
*/
|
||||||
|
$response = $client->call(Client::METHOD_POST, '/validator/debug', [
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
], json_decode(file_get_contents($directory.$file), true));
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$response['body'] = json_decode($response['body'], true);
|
||||||
$this->assertTrue(empty($response['body']));
|
|
||||||
|
|
||||||
unlink(realpath(__DIR__ . '/../../resources/open-api3.json'));
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
|
||||||
|
if(!empty($response['body'])){
|
||||||
|
var_dump($directory.$file);
|
||||||
|
var_dump($response['body']);
|
||||||
|
}
|
||||||
|
$this->assertTrue(empty($response['body']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testResponseHeader() {
|
public function testResponseHeader() {
|
||||||
|
|
Loading…
Reference in a new issue