Merge remote-tracking branch 'origin/feat-database-indexing' into feat-enum-attributes

This commit is contained in:
kodumbeats committed 2021-10-06 20:36:25 -04:00
commit ec5d2ed591
69 files changed
+5083 -844

No files matched your search

+2 -2
View File
@@ -577,7 +577,7 @@ class Database
{
if (!isset(self::$filters[$name])) {
return $value;
throw new Exception('Filter not found');
throw new Exception("Filter '{$name}' not found");
}
try {
@@ -599,7 +599,7 @@ class Database
{
if (!isset(self::$filters[$name])) {
return $value;
throw new Exception('Filter not found');
throw new Exception("Filter '{$name}' not found");
}
try {
+113 -32
View File
@@ -4,7 +4,6 @@ namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format;
use Appwrite\Template\Template;
use stdClass;
use Utopia\Validator;
class OpenAPI3 extends Format
@@ -21,6 +20,34 @@ class OpenAPI3 extends Format
return 'Open API 3';
}
/**
* Get Used Models
*
* Recursively get all used models
*
* @param object $model
* @param array $models
*
* @return void
*/
protected function getUsedModels($model, array &$usedModels)
{
if (is_string($model) && !in_array($model, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) {
$usedModels[] = $model;
return;
}
if (!is_object($model)) return;
foreach ($model->getRules() as $rule) {
if(\is_array($rule['type'])) {
foreach ($rule['type'] as $type) {
$this->getUsedModels($type, $usedModels);
}
} else {
$this->getUsedModels($rule['type'], $usedModels);
}
}
}
/**
* Parse
*
@@ -71,7 +98,7 @@ class OpenAPI3 extends Format
if (isset($output['components']['securitySchemes']['Project'])) {
$output['components']['securitySchemes']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
}
if (isset($output['components']['securitySchemes']['Key'])) {
$output['components']['securitySchemes']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
}
@@ -79,7 +106,7 @@ class OpenAPI3 extends Format
if (isset($output['securityDefinitions']['JWT'])) {
$output['securityDefinitions']['JWT']['x-appwrite'] = ['demo' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...'];
}
if (isset($output['components']['securitySchemes']['Locale'])) {
$output['components']['securitySchemes']['Locale']['x-appwrite'] = ['demo' => 'en'];
}
@@ -103,7 +130,7 @@ class OpenAPI3 extends Format
$id = $route->getLabel('sdk.method', \uniqid());
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : 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', []);
$sdkPlatofrms = [];
@@ -127,7 +154,7 @@ class OpenAPI3 extends Format
if(empty($routeSecurity)) {
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
}
$temp = [
'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id),
@@ -153,13 +180,24 @@ class OpenAPI3 extends Format
];
foreach ($this->models as $key => $value) {
if($value->getType() === $model) {
$model = $value;
break;
if(\is_array($model)) {
$model = \array_map(function($m) use($value) {
if($m === $value->getType()) {
return $value;
}
return $m;
}, $model);
} else {
if($value->getType() === $model) {
$model = $value;
break;
}
}
}
if($model->isNone()) {
if(!(\is_array($model)) && $model->isNone()) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => (in_array($produces, [
'image/*',
@@ -176,17 +214,43 @@ class OpenAPI3 extends Format
// ],
];
} else {
$usedModels[] = $model->getType();
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
'content' => [
$produces => [
'schema' => [
'$ref' => '#/components/schemas/'.$model->getType(),
if(\is_array($model)) {
$modelDescription = \join(', or ', \array_map(function ($m) {
return $m->getName();
}, $model));
// model has multiple possible responses, we will use oneOf
foreach ($model as $m) {
$usedModels[] = $m->getType();
}
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $modelDescription,
'content' => [
$produces => [
'schema' => [
'oneOf' => \array_map(function($m) {
return ['$ref' => '#/components/schemas/'.$m->getType()];
}, $model)
],
],
],
],
];
];
} else {
// Response definition using one type
$usedModels[] = $model->getType();
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
'content' => [
$produces => [
'schema' => [
'$ref' => '#/components/schemas/'.$model->getType(),
],
],
],
];
}
}
if($route->getLabel('sdk.response.code', 500) === 204) {
@@ -196,7 +260,7 @@ class OpenAPI3 extends Format
if ((!empty($scope))) { // && 'public' != $scope
$securities = ['Project' => []];
foreach($route->getLabel('sdk.auth', []) as $security) {
if(array_key_exists($security, $this->keys)) {
$securities[$security] = [];
@@ -255,7 +319,7 @@ class OpenAPI3 extends Format
case 'Utopia\Validator\JSON':
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$param['default'] = (empty($param['default'])) ? new stdClass() : $param['default'];
$param['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
$node['schema']['type'] = 'object';
$node['schema']['x-example'] = '{}';
//$node['schema']['format'] = 'json';
@@ -352,11 +416,7 @@ class OpenAPI3 extends Format
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
foreach ($this->models as $model) {
foreach ($model->getRules() as $rule) {
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
$usedModels[] = $rule['type'];
}
}
$this->getUsedModels($model, $usedModels);
}
foreach ($this->models as $model) {
if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') {
@@ -378,7 +438,7 @@ class OpenAPI3 extends Format
if($model->isAny()) {
$output['components']['schemas'][$model->getType()]['additionalProperties'] = true;
}
if(!empty($required)) {
$output['components']['schemas'][$model->getType()]['required'] = $required;
}
@@ -393,7 +453,7 @@ class OpenAPI3 extends Format
case 'json':
$type = 'string';
break;
case 'integer':
$type = 'integer';
$format = 'int32';
@@ -403,18 +463,39 @@ class OpenAPI3 extends Format
$type = 'number';
$format = 'float';
break;
case 'double':
$type = 'number';
$format = 'double';
break;
case 'boolean':
$type = 'boolean';
break;
default:
$type = 'object';
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
$items = [
'$ref' => '#/components/schemas/'.$rule['type'],
];
if(\is_array($rule['type'])) {
if($rule['array']) {
$items = [
'anyOf' => \array_map(function($type) {
return ['$ref' => '#/components/schemas/'.$type];
}, $rule['type'])
];
} else {
$items = [
'oneOf' => \array_map(function($type) {
return ['$ref' => '#/components/schemas/'.$type];
}, $rule['type'])
];
}
} else {
$items = [
'$ref' => '#/components/schemas/'.$rule['type'],
];
}
break;
}
+114 -35
View File
@@ -4,7 +4,6 @@ namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format;
use Appwrite\Template\Template;
use stdClass;
use Utopia\Validator;
class Swagger2 extends Format
@@ -21,6 +20,34 @@ class Swagger2 extends Format
return 'Swagger 2';
}
/**
* Get Used Models
*
* Recursively get all used models
*
* @param object $model
* @param array $models
*
* @return void
*/
protected function getUsedModels($model, array &$usedModels)
{
if (is_string($model) && !in_array($model, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) {
$usedModels[] = $model;
return;
}
if (!is_object($model)) return;
foreach ($model->getRules() as $rule) {
if(\is_array($rule['type'])) {
foreach ($rule['type'] as $type) {
$this->getUsedModels($type, $usedModels);
}
} else {
$this->getUsedModels($rule['type'], $usedModels);
}
}
}
/**
* Parse
*
@@ -69,15 +96,15 @@ class Swagger2 extends Format
if (isset($output['securityDefinitions']['Project'])) {
$output['securityDefinitions']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
}
if (isset($output['securityDefinitions']['Key'])) {
$output['securityDefinitions']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
}
if (isset($output['securityDefinitions']['JWT'])) {
$output['securityDefinitions']['JWT']['x-appwrite'] = ['demo' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...'];
}
if (isset($output['securityDefinitions']['Locale'])) {
$output['securityDefinitions']['Locale']['x-appwrite'] = ['demo' => 'en'];
}
@@ -125,7 +152,7 @@ class Swagger2 extends Format
if(empty($routeSecurity)) {
$sdkPlatofrms[] = APP_PLATFORM_CLIENT;
}
$temp = [
'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id),
@@ -155,13 +182,22 @@ class Swagger2 extends Format
}
foreach ($this->models as $key => $value) {
if($value->getType() === $model) {
$model = $value;
break;
if(\is_array($model)) {
$model = \array_map(function($m) use($value) {
if($m === $value->getType()) {
return $value;
}
return $m;
}, $model);
} else {
if($value->getType() === $model) {
$model = $value;
break;
}
}
}
if($model->isNone()) {
if(!(\is_array($model)) && $model->isNone()) {
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => (in_array($produces, [
'image/*',
@@ -178,13 +214,41 @@ class Swagger2 extends Format
],
];
} else {
$usedModels[] = $model->getType();
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
'schema' => [
'$ref' => '#/definitions/'.$model->getType(),
],
];
if(\is_array($model)) {
$modelDescription = \join(', or ', \array_map(function ($m) {
return $m->getName();
}, $model));
// model has multiple possible responses, we will use oneOf
foreach ($model as $m) {
$usedModels[] = $m->getType();
}
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $modelDescription,
'content' => [
$produces => [
'schema' => [
'oneOf' => \array_map(function($m) {
return ['$ref' => '#/definitions/'.$m->getType()];
}, $model)
],
],
],
];
} else {
// Response definition using one type
$usedModels[] = $model->getType();
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
'content' => [
$produces => [
'schema' => [
'$ref' => '#/definitions/'.$model->getType(),
],
],
],
];
}
}
if(in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) {
@@ -194,7 +258,7 @@ class Swagger2 extends Format
if ((!empty($scope))) { // && 'public' != $scope
$securities = ['Project' => []];
foreach($route->getLabel('sdk.auth', []) as $security) {
if(array_key_exists($security, $this->keys)) {
$securities[$security] = [];
@@ -204,7 +268,7 @@ class Swagger2 extends Format
$temp['x-appwrite']['auth'] = array_slice($securities, 0, $this->authCount);
$temp['security'][] = $securities;
}
$body = [
'name' => 'payload',
'in' => 'body',
@@ -252,7 +316,7 @@ class Swagger2 extends Format
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$node['type'] = 'object';
$param['default'] = (empty($param['default'])) ? new stdClass() : $param['default'];
$param['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
$node['x-example'] = '{}';
//$node['format'] = 'json';
break;
@@ -354,15 +418,9 @@ class Swagger2 extends Format
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
foreach ($this->models as $model) {
foreach ($model->getRules() as $rule) {
if (
in_array($model->getType(), $usedModels)
&& !in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])
) {
$usedModels[] = $rule['type'];
}
}
$this->getUsedModels($model, $usedModels);
}
foreach ($this->models as $model) {
if (!in_array($model->getType(), $usedModels)) {
continue;
@@ -383,7 +441,7 @@ class Swagger2 extends Format
if($model->isAny()) {
$output['definitions'][$model->getType()]['additionalProperties'] = true;
}
if(!empty($required)) {
$output['definitions'][$model->getType()]['required'] = $required;
}
@@ -398,7 +456,7 @@ class Swagger2 extends Format
case 'json':
$type = 'string';
break;
case 'integer':
$type = 'integer';
$format = 'int32';
@@ -408,19 +466,40 @@ class Swagger2 extends Format
$type = 'number';
$format = 'float';
break;
case 'double':
$type = 'number';
$format = 'double';
break;
case 'boolean':
$type = 'boolean';
break;
default:
$type = 'object';
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
$items = [
'type' => $type,
'$ref' => '#/definitions/'.$rule['type'],
];
if(\is_array($rule['type'])) {
if($rule['array']) {
$items = [
'anyOf' => \array_map(function($type) {
return ['$ref' => '#/definitions/'.$type];
}, $rule['type'])
];
} else {
$items = [
'oneOf' => \array_map(function($type) {
return ['$ref' => '#/definitions/'.$type];
}, $rule['type'])
];
}
} else {
$items = [
'type' => $type,
'$ref' => '#/definitions/'.$rule['type'],
];
}
break;
}
+64 -1
View File
@@ -94,7 +94,7 @@ class Stats
$functionExecutionTime = $this->params['functionExecutionTime'] ?? 0;
$functionStatus = $this->params['functionStatus'] ?? '';
$tags = ",project={$projectId},version=" . App::getEnv('_APP_VERSION', 'UNKNOWN');
$tags = ",projectId={$projectId},version=" . App::getEnv('_APP_VERSION', 'UNKNOWN');
// the global namespace is prepended to every key (optional)
$this->statsd->setNamespace($this->namespace);
@@ -112,7 +112,70 @@ class Stats
$this->statsd->count('network.outbound' . $tags, $networkResponseSize);
$this->statsd->count('network.all' . $tags, $networkRequestSize + $networkResponseSize);
$dbMetrics = [
'database.collections.create',
'database.collections.read',
'database.collections.update',
'database.collections.delete',
'database.documents.create',
'database.documents.read',
'database.documents.update',
'database.documents.delete',
];
foreach ($dbMetrics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
$tags = ",projectId={$projectId},collectionId=" . ($this->params['collectionId'] ?? '');
$this->statsd->increment($metric . $tags);
}
}
$storageMertics = [
'storage.files.create',
'storage.files.read',
'storage.files.update',
'storage.files.delete',
];
foreach ($storageMertics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
$tags = ",projectId={$projectId},bucketId=" . ($this->params['bucketId'] ?? '');
$this->statsd->increment($metric . $tags);
}
}
$usersMetrics = [
'users.create',
'users.read',
'users.update',
'users.delete',
];
foreach ($usersMetrics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
$tags = ",projectId={$projectId}";
$this->statsd->increment($metric . $tags);
}
}
$sessionsMetrics = [
'users.sessions.create',
'users.sessions.delete',
];
foreach ($sessionsMetrics as $metric) {
$value = $this->params[$metric] ?? 0;
if ($value >= 1) {
$tags = ",projectId={$projectId},provider=". ($this->params['provider'] ?? '');
$this->statsd->count($metric . $tags, $value);
}
}
if ($storage >= 1) {
$tags = ",projectId={$projectId},bucketId=" . ($this->params['bucketId'] ?? '');
$this->statsd->count('storage.all' . $tags, $storage);
}
+47 -4
View File
@@ -42,6 +42,7 @@ use Appwrite\Utopia\Response\Model\Team;
use Appwrite\Utopia\Response\Model\Locale;
use Appwrite\Utopia\Response\Model\Log;
use Appwrite\Utopia\Response\Model\Membership;
use Appwrite\Utopia\Response\Model\Metric;
use Appwrite\Utopia\Response\Model\Permissions;
use Appwrite\Utopia\Response\Model\Phone;
use Appwrite\Utopia\Response\Model\Platform;
@@ -52,7 +53,13 @@ use Appwrite\Utopia\Response\Model\Token;
use Appwrite\Utopia\Response\Model\Webhook;
use Appwrite\Utopia\Response\Model\Preferences;
use Appwrite\Utopia\Response\Model\Mock; // Keep last
use stdClass;
use Appwrite\Utopia\Response\Model\UsageBuckets;
use Appwrite\Utopia\Response\Model\UsageCollection;
use Appwrite\Utopia\Response\Model\UsageDatabase;
use Appwrite\Utopia\Response\Model\UsageFunctions;
use Appwrite\Utopia\Response\Model\UsageProject;
use Appwrite\Utopia\Response\Model\UsageStorage;
use Appwrite\Utopia\Response\Model\UsageUsers;
/**
* @method Response public function setStatusCode(int $code = 200)
@@ -65,8 +72,17 @@ class Response extends SwooleResponse
const MODEL_LOG = 'log';
const MODEL_LOG_LIST = 'logList';
const MODEL_ERROR = 'error';
const MODEL_METRIC = 'metric';
const MODEL_METRIC_LIST = 'metricList';
const MODEL_ERROR_DEV = 'errorDev';
const MODEL_BASE_LIST = 'baseList';
const MODEL_USAGE_DATABASE = 'usageDatabase';
const MODEL_USAGE_COLLECTION = 'usageCollection';
const MODEL_USAGE_USERS = 'usageUsers';
const MODEL_USAGE_BUCKETS = 'usageBuckets';
const MODEL_USAGE_STORAGE = 'usageStorage';
const MODEL_USAGE_FUNCTIONS = 'usageFunctions';
const MODEL_USAGE_PROJECT = 'usageProject';
// Database
const MODEL_COLLECTION = 'collection';
@@ -144,6 +160,7 @@ class Response extends SwooleResponse
// Deprecated
const MODEL_PERMISSIONS = 'permissions';
const MODEL_RULE = 'rule';
const MODEL_TASK = 'task';
// Tests (keep last)
const MODEL_MOCK = 'mock';
@@ -194,6 +211,7 @@ class Response extends SwooleResponse
->setModel(new BaseList('Languages List', self::MODEL_LANGUAGE_LIST, 'languages', self::MODEL_LANGUAGE))
->setModel(new BaseList('Currencies List', self::MODEL_CURRENCY_LIST, 'currencies', self::MODEL_CURRENCY))
->setModel(new BaseList('Phones List', self::MODEL_PHONE_LIST, 'phones', self::MODEL_PHONE))
->setModel(new BaseList('Metric List', self::MODEL_METRIC_LIST, 'metrics', self::MODEL_METRIC, true, false))
// Entities
->setModel(new Collection())
->setModel(new Attribute())
@@ -231,6 +249,14 @@ class Response extends SwooleResponse
->setModel(new Language())
->setModel(new Currency())
->setModel(new Phone())
->setModel(new Metric())
->setModel(new UsageDatabase())
->setModel(new UsageCollection())
->setModel(new UsageUsers())
->setModel(new UsageStorage())
->setModel(new UsageBuckets())
->setModel(new UsageFunctions())
->setModel(new UsageProject())
// Verification
// Recovery
// Tests (keep last)
@@ -304,7 +330,7 @@ class Response extends SwooleResponse
$output = self::getFilter()->parse($output, $model);
}
$this->json(!empty($output) ? $output : new stdClass());
$this->json(!empty($output) ? $output : new \stdClass());
}
/**
@@ -344,7 +370,24 @@ class Response extends SwooleResponse
foreach ($data[$key] as &$item) {
if ($item instanceof Document) {
$ruleType = (!\is_null($rule['getNestedType'])) ? $rule['getNestedType']($item) : $rule['type'];
if (\is_array($rule['type'])) {
foreach ($rule['type'] as $type) {
$condition = false;
foreach ($this->getModel($type)->conditions as $attribute => $val) {
$condition = $item->getAttribute($attribute) === $val;
if(!$condition) {
break;
}
}
if ($condition) {
$ruleType = $type;
break;
}
}
} else {
$ruleType = $rule['type'];
}
if (!array_key_exists($ruleType, $this->models)) {
throw new Exception('Missing model for rule: '. $ruleType);
}
@@ -353,7 +396,7 @@ class Response extends SwooleResponse
}
}
}
$output[$key] = $data[$key];
}
+2 -5
View File
@@ -69,13 +69,11 @@ abstract class Model
/**
* Add a New Rule
* If rule is an array of documents with varying models
* Pass callable $getNestedType that accepts Document and returns the nested response type
*
* @param string $key
* @param array $options
* @param callable $getNestedType function(Document $value): string
*/
protected function addRule(string $key, array $options, callable $getNestedType = null): self
protected function addRule(string $key, array $options): self
{
$this->rules[$key] = array_merge([
'require' => true,
@@ -83,8 +81,7 @@ abstract class Model
'description' => '',
'default' => null,
'example' => '',
'array' => false,
'getNestedType' => $getNestedType
'array' => false
], $options);
return $this;
@@ -44,6 +44,8 @@ class Attribute extends Model
;
}
public array $conditions = [];
/**
* Get Name
*
@@ -23,6 +23,10 @@ class AttributeBoolean extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_BOOLEAN
];
/**
* Get Name
*
@@ -34,7 +38,7 @@ class AttributeBoolean extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -31,6 +31,11 @@ class AttributeEmail extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_STRING,
'format' => \APP_DATABASE_ATTRIBUTE_EMAIL
];
/**
* Get Name
*
@@ -42,7 +47,7 @@ class AttributeEmail extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -39,6 +39,10 @@ class AttributeFloat extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_FLOAT,
];
/**
* Get Name
*
@@ -50,7 +54,7 @@ class AttributeFloat extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -31,6 +31,11 @@ class AttributeIP extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_STRING,
'format' => \APP_DATABASE_ATTRIBUTE_IP
];
/**
* Get Name
*
@@ -42,7 +47,7 @@ class AttributeIP extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -39,6 +39,10 @@ class AttributeInteger extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_INTEGER,
];
/**
* Get Name *
* @return string
@@ -49,7 +53,7 @@ class AttributeInteger extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -18,25 +18,18 @@ class AttributeList extends Model
'example' => 5,
])
->addRule('attributes', [
'type' => Response::MODEL_ATTRIBUTE,
'type' => [
Response::MODEL_ATTRIBUTE_BOOLEAN,
Response::MODEL_ATTRIBUTE_INTEGER,
Response::MODEL_ATTRIBUTE_FLOAT,
Response::MODEL_ATTRIBUTE_EMAIL,
Response::MODEL_ATTRIBUTE_URL,
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute
],
'description' => 'List of attributes.',
'default' => [],
'array' => true,
'getNestedType' => function(Document $attribute) {
return match($attribute->getAttribute('type')) {
self::TYPE_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN,
self::TYPE_INTEGER => Response::MODEL_ATTRIBUTE_INTEGER,
self::TYPE_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT,
self::TYPE_STRING => match($attribute->getAttribute('format')) {
APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL,
APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM,
APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP,
APP_DATABASE_ATTRIBUTE_URL => Response::MODEL_ATTRIBUTE_URL,
default => Response::MODEL_ATTRIBUTE_STRING,
},
default => Response::MODEL_ATTRIBUTE,
};
},
'array' => true
])
;
}
@@ -52,7 +45,7 @@ class AttributeList extends Model
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -29,6 +29,10 @@ class AttributeString extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_STRING,
];
/**
* Get Name
*
@@ -40,7 +44,7 @@ class AttributeString extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -31,6 +31,11 @@ class AttributeURL extends Attribute
;
}
public array $conditions = [
'type' => self::TYPE_STRING,
'format' => \APP_DATABASE_ATTRIBUTE_URL
];
/**
* Get Name
*
@@ -42,7 +47,7 @@ class AttributeURL extends Attribute
}
/**
* Get Collection
* Get Type
*
* @return string
*/
@@ -4,8 +4,6 @@ namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use Utopia\Database\Document;
use stdClass;
class Collection extends Model
{
@@ -45,32 +43,25 @@ class Collection extends Model
'example' => 'document',
])
->addRule('attributes', [
'type' => Response::MODEL_ATTRIBUTE,
'type' => [
Response::MODEL_ATTRIBUTE_BOOLEAN,
Response::MODEL_ATTRIBUTE_INTEGER,
Response::MODEL_ATTRIBUTE_FLOAT,
Response::MODEL_ATTRIBUTE_EMAIL,
Response::MODEL_ATTRIBUTE_URL,
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute
],
'description' => 'Collection attributes.',
'default' => [],
'example' => new stdClass,
'example' => new \stdClass,
'array' => true,
'getNestedType' => function(Document $attribute) {
return match($attribute->getAttribute('type')) {
self::TYPE_BOOLEAN => Response::MODEL_ATTRIBUTE_BOOLEAN,
self::TYPE_INTEGER => Response::MODEL_ATTRIBUTE_INTEGER,
self::TYPE_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT,
self::TYPE_STRING => match($attribute->getAttribute('format')) {
APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL,
APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM,
APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP,
APP_DATABASE_ATTRIBUTE_URL => Response::MODEL_ATTRIBUTE_URL,
default => Response::MODEL_ATTRIBUTE_STRING,
},
default => Response::MODEL_ATTRIBUTE,
};
},
])
->addRule('indexes', [
'type' => Response::MODEL_INDEX,
'description' => 'Collection indexes.',
'default' => [],
'example' => new stdClass,
'example' => new \stdClass,
'array' => true
])
;
@@ -0,0 +1,47 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class Metric extends Model
{
public function __construct()
{
$this
->addRule('value', [
'type' => self::TYPE_INTEGER,
'description' => 'The value of this metric at the timestamp.',
'default' => -1,
'example' => 1,
])
->addRule('timestamp', [
'type' => self::TYPE_INTEGER,
'description' => 'The UNIX timestamp at which this metric was aggregated.',
'default' => 0,
'example' => 1592981250
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'Metric';
}
/**
* Get Collection
*
* @return string
*/
public function getType():string
{
return Response::MODEL_METRIC;
}
}
@@ -2,7 +2,6 @@
namespace Appwrite\Utopia\Response\Model;
use stdClass;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
use Utopia\Config\Config;
@@ -100,28 +99,28 @@ class Project extends Model
'type' => Response::MODEL_PLATFORM,
'description' => 'List of Platforms.',
'default' => [],
'example' => new stdClass,
'example' => new \stdClass,
'array' => true,
])
->addRule('webhooks', [
'type' => Response::MODEL_WEBHOOK,
'description' => 'List of Webhooks.',
'default' => [],
'example' => new stdClass,
'example' => new \stdClass,
'array' => true,
])
->addRule('keys', [
'type' => Response::MODEL_KEY,
'description' => 'List of API Keys.',
'default' => [],
'example' => new stdClass,
'example' => new \stdClass,
'array' => true,
])
->addRule('domains', [
'type' => Response::MODEL_DOMAIN,
'description' => 'List of Domains.',
'default' => [],
'example' => new stdClass,
'example' => new \stdClass,
'array' => true,
])
;
@@ -0,0 +1,76 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageBuckets extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('files.count', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for total number of files in this bucket.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('files.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for files created.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('files.read', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for files read.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('files.update', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for files updated.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('files.delete', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for files deleted.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'UsageBuckets';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_BUCKETS;
}
}
@@ -0,0 +1,76 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageCollection extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('documents.count', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.read', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.update', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.delete', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'UsageCollection';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_COLLECTION;
}
}
@@ -0,0 +1,111 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageDatabase extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('documents.count', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for total number of documents.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('collections.count', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for total number of collections.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents created.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.read', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents read.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.update', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents updated.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents.delete', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for documents deleted.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('collections.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for collections created.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('collections.read', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for collections read.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('collections.update', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for collections updated.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('collections.delete', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for collections delete.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'UsageDatabase';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_DATABASE;
}
}
@@ -0,0 +1,62 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageFunctions extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('functions.executions', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for function executions.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('functions.failures', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for function execution failures.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('functions.compute', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for function execution duration.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'UsageFunctions';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_FUNCTIONS;
}
}
@@ -0,0 +1,90 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageProject extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('requests', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for number of requests.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('network', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for consumed bandwidth.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('functions', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for function executions.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('documents', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for number of documents.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('collections', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for number of collections.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('users', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for number of users.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('storage', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for the occupied storage size (in bytes).',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'UsageProject';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_PROJECT;
}
}
@@ -0,0 +1,55 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageStorage extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('storage', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for the occupied storage size (in bytes).',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('files', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for total number of files.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'StorageUsage';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_STORAGE;
}
}
@@ -0,0 +1,97 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class UsageUsers extends Model
{
public function __construct()
{
$this
->addRule('range', [
'type' => self::TYPE_STRING,
'description' => 'The time range of the usage stats.',
'default' => '',
'example' => '30d',
])
->addRule('users.count', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for total number of users.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('users.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for users created.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('users.read', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for users read.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('users.update', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for users updated.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('users.delete', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for users deleted.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('sessions.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for sessions created.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('sessions.provider.create', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for sessions created for a provider ( email, anonymous or oauth2 ).',
'default' => [],
'example' => new \stdClass,
'array' => true
])
->addRule('sessions.delete', [
'type' => Response::MODEL_METRIC_LIST,
'description' => 'Aggregated stats for sessions deleted.',
'default' => [],
'example' => new \stdClass,
'array' => true
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'UsageUsers';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_USAGE_USERS;
}
}