diff --git a/example.php b/example.php index 6af298baf..62ab280f2 100644 --- a/example.php +++ b/example.php @@ -37,8 +37,8 @@ function getSSLPage($url) { } // Leave the platform you want uncommented - $platform = 'client'; - // $platform = 'console'; +// $platform = 'client'; + $platform = 'console'; // $platform = 'server'; $spec = getSSLPage("https://raw.githubusercontent.com/appwrite/appwrite/master/app/config/specs/swagger2-latest-{$platform}.json"); diff --git a/src/SDK/Language.php b/src/SDK/Language.php index 0a7a259f7..68a90cfbe 100644 --- a/src/SDK/Language.php +++ b/src/SDK/Language.php @@ -41,7 +41,7 @@ abstract public function getFiles(): array; * @param array $parameter * @return string */ - abstract public function getTypeName(array $parameter): string; + abstract public function getTypeName(array $parameter, array $spec = []): string; /** * @param array $param @@ -84,7 +84,7 @@ public function getFilters(): array return []; } - protected function toUpperCaseWords(string $value): string + protected function toPascalCase(string $value): string { return ucfirst($this->toCamelCase($value)); } @@ -97,4 +97,17 @@ protected function toCamelCase($str): string $str = str_replace(" ", "", $str); return lcfirst($str); } + + protected function toSnakeCase($str): string + { + $str = \preg_replace('/([a-z])([A-Z])/', '$1 $2', $str); + $str = \explode(' ', $str); + $str = \implode('_', $str); + return \strtolower($str); + } + + protected function toUpperSnakeCase($str): string + { + return \strtoupper($this->toSnakeCase($str)); + } } diff --git a/src/SDK/Language/Android.php b/src/SDK/Language/Android.php index 5d3e90bb0..4421bfa90 100644 --- a/src/SDK/Language/Android.php +++ b/src/SDK/Language/Android.php @@ -387,6 +387,11 @@ public function getFiles(): array 'destination' => 'library/src/main/java/io/appwrite/models/{{ definition.name | caseUcfirst }}.kt', 'template' => '/android/library/src/main/java/io/appwrite/models/Model.kt.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'library/src/main/java/io/appwrite/enums/{{ enum.name | caseUcfirst }}.kt', + 'template' => '/android/library/src/main/java/io/appwrite/enums/Enum.kt.twig', + ], ]; } } diff --git a/src/SDK/Language/Dart.php b/src/SDK/Language/Dart.php index d225b3768..b61380a01 100644 --- a/src/SDK/Language/Dart.php +++ b/src/SDK/Language/Dart.php @@ -112,16 +112,28 @@ public function getKeywords(): array */ public function getIdentifierOverrides(): array { - return ['Function' => 'Func', 'default' => 'xdefault', 'required' => 'xrequired', 'async' => 'xasync']; + return [ + 'Function' => 'Func', + 'default' => 'xdefault', + 'required' => 'xrequired', + 'async' => 'xasync', + 'enum' => 'xenum', + ]; } /** * @param array $parameter * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { + if (isset($parameter['enumName'])) { + return 'enums.' . \ucfirst($parameter['enumName']); + } + if (!empty($parameter['enumValues'])) { + return 'enums.' . \ucfirst($parameter['name']); + } + switch ($parameter['type'] ?? '') { case self::TYPE_INTEGER: return 'int'; case self::TYPE_STRING: @@ -131,7 +143,7 @@ public function getTypeName(array $parameter): string case self::TYPE_BOOLEAN: return 'bool'; case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { + if (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) { return 'List<' . $this->getTypeName($parameter['array']) . '>'; } return 'List'; @@ -139,9 +151,9 @@ public function getTypeName(array $parameter): string return 'Map'; case self::TYPE_NUMBER: return 'double'; + default: + return $parameter['type']; } - - return $parameter['type']; } /** @@ -386,6 +398,11 @@ public function getFiles(): array 'destination' => '/lib/models.dart', 'template' => 'dart/lib/models.dart.twig', ], + [ + 'scope' => 'default', + 'destination' => '/lib/enums.dart', + 'template' => 'dart/lib/enums.dart.twig', + ], [ 'scope' => 'service', 'destination' => '/lib/services/{{service.name | caseDash}}.dart', @@ -466,6 +483,11 @@ public function getFiles(): array 'destination' => 'lib/src/input_file.dart', 'template' => 'dart/lib/src/input_file.dart.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'lib/src/enums/{{ enum.name | caseSnake }}.dart', + 'template' => 'dart/lib/src/enums/enum.dart.twig', + ], ]; } @@ -479,6 +501,9 @@ public function getFilters(): array } return implode("\n", $value); }, ['is_safe' => ['html']]), + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toCamelCase($value); + }), ]; } } diff --git a/src/SDK/Language/Deno.php b/src/SDK/Language/Deno.php index 1fdef0c0d..e85c439ea 100644 --- a/src/SDK/Language/Deno.php +++ b/src/SDK/Language/Deno.php @@ -2,6 +2,8 @@ namespace Appwrite\SDK\Language; +use Twig\TwigFilter; + class Deno extends JS { /** @@ -93,6 +95,11 @@ public function getFiles(): array 'destination' => 'docs/examples/{{service.name | caseLower}}/{{method.name | caseDash}}.md', 'template' => 'deno/docs/example.md.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'src/enums/{{ enum.name | caseDash }}.ts', + 'template' => 'deno/src/enums/enum.ts.twig', + ], ]; } @@ -100,27 +107,25 @@ public function getFiles(): array * @param array $parameter * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - return 'number'; - case self::TYPE_STRING: - return 'string'; - case self::TYPE_FILE: - return 'InputFile'; - case self::TYPE_BOOLEAN: - return 'boolean'; - case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { - return $this->getTypeName($parameter['array']) . '[]'; - } - return 'string[]'; - case self::TYPE_OBJECT: - return 'object'; + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); } - - return $parameter['type']; + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + return match ($parameter['type']) { + self::TYPE_INTEGER => 'number', + self::TYPE_STRING => 'string', + self::TYPE_FILE => 'InputFile', + self::TYPE_BOOLEAN => 'boolean', + self::TYPE_ARRAY => (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) + ? $this->getTypeName($parameter['array']) . '[]' + : 'string[]', + self::TYPE_OBJECT => 'object', + default => $parameter['type'] + }; } /** @@ -176,4 +181,13 @@ public function getParamExample(array $param): string return $output; } + + public function getFilters(): array + { + return [ + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toPascalCase($value); + }), + ]; + } } diff --git a/src/SDK/Language/DotNet.php b/src/SDK/Language/DotNet.php index f569225f2..0bd9082c7 100644 --- a/src/SDK/Language/DotNet.php +++ b/src/SDK/Language/DotNet.php @@ -149,29 +149,26 @@ public function getIdentifierOverrides(): array * @param array $parameter * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - return 'long'; - case self::TYPE_NUMBER: - return 'double'; - case self::TYPE_STRING: - return 'string'; - case self::TYPE_FILE: - return 'InputFile'; - case self::TYPE_BOOLEAN: - return 'bool'; - case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { - return 'List<' . $this->getTypeName($parameter['array']) . '>'; - } - return 'List'; - case self::TYPE_OBJECT: - return 'object'; + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); } - - return $parameter['type']; + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + return match ($parameter['type']) { + self::TYPE_INTEGER => 'long', + self::TYPE_NUMBER => 'double', + self::TYPE_STRING => 'string', + self::TYPE_BOOLEAN => 'bool', + self::TYPE_FILE => 'InputFile', + self::TYPE_ARRAY => (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) + ? 'List<' . $this->getTypeName($parameter['array']) . '>' + : 'List', + self::TYPE_OBJECT => 'object', + default => $parameter['type'] + }; } /** @@ -361,6 +358,11 @@ public function getFiles(): array 'destination' => '/src/{{ spec.title | caseUcfirst }}/Role.cs', 'template' => 'dotnet/src/Appwrite/Role.cs.twig', ], + [ + 'scope' => 'default', + 'destination' => '/src/{{ spec.title | caseUcfirst }}/Converters/ValueClassConverter.cs', + 'template' => 'dotnet/src/Appwrite/Converters/ValueClassConverter.cs.twig', + ], [ 'scope' => 'default', 'destination' => '/src/{{ spec.title | caseUcfirst }}/Extensions/Extensions.cs', @@ -395,6 +397,16 @@ public function getFiles(): array 'scope' => 'definition', 'destination' => '/src/{{ spec.title | caseUcfirst }}/Models/{{ definition.name | caseUcfirst | overrideIdentifier }}.cs', 'template' => 'dotnet/src/Appwrite/Models/Model.cs.twig', + ], + [ + 'scope' => 'enum', + 'destination' => '/src/{{ spec.title | caseUcfirst }}/Enums/{{ enum.name | caseUcfirst | overrideIdentifier }}.cs', + 'template' => 'dotnet/src/Appwrite/Enums/Enum.cs.twig', + ], + [ + 'scope' => 'default', + 'destination' => '/src/{{ spec.title | caseUcfirst }}/Enums/IEnum.cs', + 'template' => 'dotnet/src/Appwrite/Enums/IEnum.cs.twig', ] ]; } @@ -408,7 +420,10 @@ public function getFilters(): array $value[$key] = " /// " . wordwrap($line, 75, "\n /// "); } return implode("\n", $value); - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toPascalCase($value); + }), ]; } } diff --git a/src/SDK/Language/Flutter.php b/src/SDK/Language/Flutter.php index 806e19054..77f5c66bf 100644 --- a/src/SDK/Language/Flutter.php +++ b/src/SDK/Language/Flutter.php @@ -60,6 +60,11 @@ public function getFiles(): array 'destination' => '/lib/models.dart', 'template' => 'dart/lib/models.dart.twig', ], + [ + 'scope' => 'default', + 'destination' => '/lib/enums.dart', + 'template' => 'dart/lib/enums.dart.twig', + ], [ 'scope' => 'default', 'destination' => '/lib/permission.dart', @@ -330,6 +335,11 @@ public function getFiles(): array 'destination' => '.travis.yml', 'template' => 'flutter/.travis.yml.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'lib/src/enums/{{ enum.name | caseSnake }}.dart', + 'template' => 'dart/lib/src/enums/enum.dart.twig', + ], ]; } } diff --git a/src/SDK/Language/Go.php b/src/SDK/Language/Go.php index ebb4347e6..07c1f3e2b 100644 --- a/src/SDK/Language/Go.php +++ b/src/SDK/Language/Go.php @@ -106,25 +106,17 @@ public function getFiles(): array * @param array $nestedTypes * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - return 'int'; - case self::TYPE_NUMBER: - return 'float64'; - case self::TYPE_FILE: - case self::TYPE_STRING: - return 'string'; - case self::TYPE_BOOLEAN: - return 'bool'; - case self::TYPE_OBJECT: - return 'interface{}'; - case self::TYPE_ARRAY: - return '[]interface{}'; - } - - return $parameter['type']; + return match ($parameter['type']) { + self::TYPE_INTEGER => 'int', + self::TYPE_NUMBER => 'float64', + self::TYPE_FILE, self::TYPE_STRING => 'string', + self::TYPE_BOOLEAN => 'bool', + self::TYPE_OBJECT => 'interface{}', + self::TYPE_ARRAY => '[]interface{}', + default => $parameter['type'], + }; } /** @@ -247,7 +239,10 @@ public function getFilters(): array $value[$key] = "// " . wordwrap($line, 75, "\n// "); } return implode("\n", $value); - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toUpperSnakeCase($value); + }), ]; } } diff --git a/src/SDK/Language/GraphQL.php b/src/SDK/Language/GraphQL.php index 628f7598f..ca4f6735e 100644 --- a/src/SDK/Language/GraphQL.php +++ b/src/SDK/Language/GraphQL.php @@ -16,7 +16,7 @@ public function getName(): string * @param $type * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { $type = ''; @@ -34,7 +34,7 @@ public function getTypeName(array $parameter): string $type = 'Bool'; break; case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { + if (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) { $type = '[' . $this->getTypeName($parameter['array']) . ']'; break; } diff --git a/src/SDK/Language/HTTP.php b/src/SDK/Language/HTTP.php index 1e674c945..f1abcc4a9 100644 --- a/src/SDK/Language/HTTP.php +++ b/src/SDK/Language/HTTP.php @@ -30,7 +30,7 @@ public function getIdentifierOverrides(): array * @return string * @throws Exception */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { throw new Exception('Method not supported for HTTP APIs'); } diff --git a/src/SDK/Language/JS.php b/src/SDK/Language/JS.php index c41727e36..78ee3dea6 100644 --- a/src/SDK/Language/JS.php +++ b/src/SDK/Language/JS.php @@ -3,6 +3,7 @@ namespace Appwrite\SDK\Language; use Appwrite\SDK\Language; +use Twig\TwigFilter; abstract class JS extends Language { @@ -122,14 +123,21 @@ public function getIdentifierOverrides(): array * @param array $nestedTypes * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); + } + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + switch ($parameter['type']) { case self::TYPE_INTEGER: case self::TYPE_NUMBER: return 'number'; case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { + if (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) { return $this->getTypeName($parameter['array']) . '[]'; } return 'string[]'; @@ -192,4 +200,13 @@ public function getParamDefault(array $param): string return $output; } + + public function getFilters(): array + { + return [ + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toUpperSnakeCase($value); + }), + ]; + } } diff --git a/src/SDK/Language/Kotlin.php b/src/SDK/Language/Kotlin.php index a7a4c5aea..bde9513cd 100644 --- a/src/SDK/Language/Kotlin.php +++ b/src/SDK/Language/Kotlin.php @@ -103,29 +103,26 @@ public function getIdentifierOverrides(): array * @param $type * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - return 'Long'; - case self::TYPE_NUMBER: - return 'Double'; - case self::TYPE_STRING: - return 'String'; - case self::TYPE_FILE: - return 'InputFile'; - case self::TYPE_BOOLEAN: - return 'Boolean'; - case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { - return 'List<' . $this->getTypeName($parameter['array']) . '>'; - } - return 'List'; - case self::TYPE_OBJECT: - return 'Any'; + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); } - - return $parameter['type']; + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + return match ($parameter['type']) { + self::TYPE_INTEGER => 'Long', + self::TYPE_NUMBER => 'Double', + self::TYPE_STRING => 'String', + self::TYPE_FILE => 'InputFile', + self::TYPE_BOOLEAN => 'Boolean', + self::TYPE_ARRAY => (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) + ? 'List<' . $this->getTypeName($parameter['array']) . '>' + : 'List', + self::TYPE_OBJECT => 'Any', + default => $parameter['type'], + }; } /** @@ -419,6 +416,11 @@ public function getFiles(): array 'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/models/{{ definition.name | caseUcfirst }}.kt', 'template' => '/kotlin/src/main/kotlin/io/appwrite/models/Model.kt.twig', ], + [ + 'scope' => 'enum', + 'destination' => '/src/main/kotlin/{{ sdk.namespace | caseSlash }}/enums/{{ enum.name | caseUcfirst }}.kt', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/enums/Enum.kt.twig', + ], ]; } @@ -437,6 +439,13 @@ public function getFilters(): array new TwigFilter('hasGenericType', function (string $model, array $spec) { return $this->hasGenericType($model, $spec); }), + new TwigFilter('caseEnumKey', function (string $value) { + if (isset($this->getIdentifierOverrides()[$value])) { + $value = $this->getIdentifierOverrides()[$value]; + } + $value = \preg_replace('/[^a-zA-Z0-9]/', '', $value); + return $this->toUpperSnakeCase($value); + }), ]; } @@ -457,7 +466,7 @@ protected function getReturnType(array $method, array $spec, string $namespace, return 'Any'; } - $ret = $this->toUpperCaseWords($method['responseModel']); + $ret = $this->toPascalCase($method['responseModel']); if ($this->hasGenericType($method['responseModel'], $spec)) { $ret .= '<' . $generic . '>'; @@ -469,15 +478,15 @@ protected function getReturnType(array $method, array $spec, string $namespace, protected function getModelType(array $definition, array $spec, string $generic = 'T'): string { if ($this->hasGenericType($definition['name'], $spec)) { - return $this->toUpperCaseWords($definition['name']) . '<' . $generic . '>'; + return $this->toPascalCase($definition['name']) . '<' . $generic . '>'; } - return $this->toUpperCaseWords($definition['name']); + return $this->toPascalCase($definition['name']); } protected function getPropertyType(array $property, array $spec, string $generic = 'T'): string { if (\array_key_exists('sub_schema', $property)) { - $type = $this->toUpperCaseWords($property['sub_schema']); + $type = $this->toPascalCase($property['sub_schema']); if ($this->hasGenericType($property['sub_schema'], $spec)) { $type .= '<' . $generic . '>'; diff --git a/src/SDK/Language/Node.php b/src/SDK/Language/Node.php index 435e1cce0..6e55ea482 100644 --- a/src/SDK/Language/Node.php +++ b/src/SDK/Language/Node.php @@ -17,22 +17,26 @@ public function getName(): string * @param array $nestedTypes * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - case self::TYPE_NUMBER: - return 'number'; - case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { - return $this->getTypeName($parameter['array']) . '[]'; - } - return 'string[]'; - case self::TYPE_FILE: - return 'InputFile'; + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); } - - return $parameter['type']; + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + return match ($parameter['type']) { + self::TYPE_INTEGER, + self::TYPE_NUMBER => 'number', + self::TYPE_STRING => 'string', + self::TYPE_FILE => 'InputFile', + self::TYPE_BOOLEAN => 'boolean', + self::TYPE_OBJECT => 'object', + self::TYPE_ARRAY => (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) + ? $this->getTypeName($parameter['array']) . '[]' + : 'string[]', + default => $parameter['type'], + }; } /** @@ -126,6 +130,11 @@ public function getFiles(): array 'destination' => '.travis.yml', 'template' => 'node/.travis.yml.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'lib/enums/{{ enum.name | caseDash }}.js', + 'template' => 'node/lib/enums/enum.js.twig', + ], ]; } diff --git a/src/SDK/Language/PHP.php b/src/SDK/Language/PHP.php index 99ad8740e..03ec2305d 100644 --- a/src/SDK/Language/PHP.php +++ b/src/SDK/Language/PHP.php @@ -212,6 +212,11 @@ public function getFiles(): array 'destination' => '/src/{{ spec.title | caseUcfirst}}/Services/{{service.name | caseUcfirst}}.php', 'template' => 'php/src/Services/Service.php.twig', ], + [ + 'scope' => 'enum', + 'destination' => '/src/{{ spec.title | caseUcfirst}}/Enums/{{ enum.name | caseUcfirst }}.php', + 'template' => 'php/src/Enums/Enum.php.twig', + ], ]; } @@ -220,29 +225,24 @@ public function getFiles(): array * @param array $nestedTypes * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_STRING: - $type = 'string'; - break; - case self::TYPE_BOOLEAN: - $type = 'bool'; - break; - case self::TYPE_NUMBER: - case self::TYPE_INTEGER: - $type = 'int'; - break; - case self::TYPE_ARRAY: - case self::TYPE_OBJECT: - $type = 'array'; - break; - case self::TYPE_FILE: - $type = 'InputFile'; - break; + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); } - - return $type . ' '; + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + return match ($parameter['type']) { + self::TYPE_STRING => 'string', + self::TYPE_BOOLEAN => 'bool', + self::TYPE_NUMBER, + self::TYPE_INTEGER => 'int', + self::TYPE_ARRAY, + self::TYPE_OBJECT => 'array', + self::TYPE_FILE => 'InputFile', + default => $parameter['type'], + }; } /** @@ -389,6 +389,13 @@ public function getFilters(): array new TwigFilter('deviceInfo', function ($value) { return php_uname('s') . '; ' . php_uname('v') . '; ' . php_uname('m'); }), + new TwigFilter('caseEnumKey', function (string $value) { + if (isset($this->getIdentifierOverrides()[$value])) { + $value = $this->getIdentifierOverrides()[$value]; + } + $value = \preg_replace('/[^a-zA-Z0-9]/', '', $value); + return $this->toUpperSnakeCase($value); + }), ]; } } diff --git a/src/SDK/Language/Python.php b/src/SDK/Language/Python.php index c8d19e639..891d0d67d 100644 --- a/src/SDK/Language/Python.php +++ b/src/SDK/Language/Python.php @@ -4,6 +4,7 @@ use Appwrite\SDK\Language; use Exception; +use Twig\TwigFilter; class Python extends Language { @@ -90,99 +91,119 @@ public function getFiles(): array { return [ [ - 'scope' => 'default', - 'destination' => 'README.md', - 'template' => 'python/README.md.twig', + 'scope' => 'default', + 'destination' => 'README.md', + 'template' => 'python/README.md.twig', ], [ - 'scope' => 'default', - 'destination' => 'CHANGELOG.md', - 'template' => 'python/CHANGELOG.md.twig', + 'scope' => 'default', + 'destination' => 'CHANGELOG.md', + 'template' => 'python/CHANGELOG.md.twig', ], [ - 'scope' => 'default', - 'destination' => 'LICENSE', - 'template' => 'python/LICENSE.twig', + 'scope' => 'default', + 'destination' => 'LICENSE', + 'template' => 'python/LICENSE.twig', ], [ - 'scope' => 'default', - 'destination' => 'setup.py', - 'template' => 'python/setup.py.twig', + 'scope' => 'default', + 'destination' => 'setup.py', + 'template' => 'python/setup.py.twig', ], [ - 'scope' => 'default', - 'destination' => 'setup.cfg', - 'template' => 'python/setup.cfg.twig', + 'scope' => 'default', + 'destination' => 'setup.cfg', + 'template' => 'python/setup.cfg.twig', ], [ - 'scope' => 'default', - 'destination' => 'requirements.txt', - 'template' => 'python/requirements.txt.twig', + 'scope' => 'default', + 'destination' => 'requirements.txt', + 'template' => 'python/requirements.txt.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/__init__.py', - 'template' => 'python/package/__init__.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/__init__.py', + 'template' => 'python/package/__init__.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/client.py', - 'template' => 'python/package/client.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/client.py', + 'template' => 'python/package/client.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/permission.py', - 'template' => 'python/package/permission.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/permission.py', + 'template' => 'python/package/permission.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/role.py', - 'template' => 'python/package/role.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/role.py', + 'template' => 'python/package/role.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/id.py', - 'template' => 'python/package/id.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/id.py', + 'template' => 'python/package/id.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/query.py', - 'template' => 'python/package/query.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/query.py', + 'template' => 'python/package/query.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/exception.py', - 'template' => 'python/package/exception.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/exception.py', + 'template' => 'python/package/exception.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/input_file.py', - 'template' => 'python/package/input_file.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/input_file.py', + 'template' => 'python/package/input_file.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/service.py', - 'template' => 'python/package/service.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/service.py', + 'template' => 'python/package/service.py.twig', ], [ - 'scope' => 'default', - 'destination' => '{{ spec.title | caseSnake}}/services/__init__.py', - 'template' => 'python/package/services/__init__.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/services/__init__.py', + 'template' => 'python/package/services/__init__.py.twig', ], [ - 'scope' => 'service', - 'destination' => '{{ spec.title | caseSnake}}/services/{{service.name | caseSnake}}.py', - 'template' => 'python/package/services/service.py.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/encoders/__init__.py', + 'template' => 'python/package/services/__init__.py.twig', ], [ - 'scope' => 'method', - 'destination' => 'docs/examples/{{service.name | caseLower}}/{{method.name | caseDash}}.md', - 'template' => 'python/docs/example.md.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/enums/__init__.py', + 'template' => 'python/package/services/__init__.py.twig', ], [ - 'scope' => 'default', - 'destination' => '.travis.yml', - 'template' => 'python/.travis.yml.twig', + 'scope' => 'default', + 'destination' => '{{ spec.title | caseSnake}}/encoders/value_class_encoder.py', + 'template' => 'python/package/encoders/value_class_encoder.py.twig', + ], + [ + 'scope' => 'service', + 'destination' => '{{ spec.title | caseSnake}}/services/{{service.name | caseSnake}}.py', + 'template' => 'python/package/services/service.py.twig', + ], + [ + 'scope' => 'method', + 'destination' => 'docs/examples/{{service.name | caseLower}}/{{method.name | caseDash}}.md', + 'template' => 'python/docs/example.md.twig', + ], + [ + 'scope' => 'default', + 'destination' => '.travis.yml', + 'template' => 'python/.travis.yml.twig', + ], + [ + 'scope' => 'enum', + 'destination' => '{{ spec.title | caseSnake}}/enums/{{ enum.name | caseSnake }}.py', + 'template' => 'python/package/enums/enum.py.twig', ], ]; } @@ -192,9 +213,24 @@ public function getFiles(): array * @return string * @throws Exception */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - throw new Exception('Method not supported for Python SDKs'); + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); + } + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } + return match ($parameter['type'] ?? '') { + self::TYPE_FILE => 'InputFile', + self::TYPE_NUMBER, + self::TYPE_INTEGER => 'float', + self::TYPE_BOOLEAN => 'bool', + self::TYPE_STRING => 'str', + self::TYPE_ARRAY => 'list', + self::TYPE_OBJECT => 'dict', + default => $parameter['type'], + }; } /** @@ -203,9 +239,9 @@ public function getTypeName(array $parameter): string */ public function getParamDefault(array $param): string { - $type = $param['type'] ?? ''; - $default = $param['default'] ?? ''; - $required = $param['required'] ?? ''; + $type = $param['type'] ?? ''; + $default = $param['default'] ?? ''; + $required = $param['required'] ?? ''; if ($required) { return ''; @@ -260,8 +296,8 @@ public function getParamDefault(array $param): string */ public function getParamExample(array $param): string { - $type = $param['type'] ?? ''; - $example = $param['example'] ?? ''; + $type = $param['type'] ?? ''; + $example = $param['example'] ?? ''; $output = ''; @@ -307,4 +343,13 @@ public function getParamExample(array $param): string return $output; } + + public function getFilters(): array + { + return [ + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toUpperSnakeCase($value); + }), + ]; + } } diff --git a/src/SDK/Language/Ruby.php b/src/SDK/Language/Ruby.php index eb50551b0..04f4869a7 100644 --- a/src/SDK/Language/Ruby.php +++ b/src/SDK/Language/Ruby.php @@ -182,6 +182,11 @@ public function getFiles(): array 'destination' => '/lib/{{ spec.title | caseDash }}/models/{{ definition.name | caseSnake }}.rb', 'template' => 'ruby/lib/container/models/model.rb.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'lib/{{ spec.title | caseSnake}}/enums/{{ enum.name | caseSnake }}.rb', + 'template' => 'ruby/lib/container/enums/enum.rb.twig', + ], ]; } @@ -190,24 +195,23 @@ public function getFiles(): array * @param array $nestedTypes * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - return 'Integer'; - case self::TYPE_NUMBER: - return 'Float'; - case self::TYPE_STRING: - return 'String'; - case self::TYPE_ARRAY: - return 'Array'; - case self::TYPE_OBJECT: - return 'Hash'; - case self::TYPE_BOOLEAN: - return ''; - default: - return $parameter['type']; + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); + } + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); } + return match ($parameter['type']) { + self::TYPE_INTEGER => 'Integer', + self::TYPE_NUMBER => 'Float', + self::TYPE_STRING => 'String', + self::TYPE_ARRAY => 'Array', + self::TYPE_OBJECT => 'Hash', + self::TYPE_BOOLEAN => '', + default => $parameter['type'], + }; } /** @@ -348,7 +352,10 @@ public function getFilters(): array $value[$key] = " # " . wordwrap($line, 75, "\n # "); } return implode("\n", $value); - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + new TwigFilter('caseEnumKey', function (string $value) { + return $this->toUpperSnakeCase($value); + }), ]; } } diff --git a/src/SDK/Language/Swift.php b/src/SDK/Language/Swift.php index 9b2e08798..db69689cd 100644 --- a/src/SDK/Language/Swift.php +++ b/src/SDK/Language/Swift.php @@ -87,6 +87,7 @@ public function getKeywords(): array "unowned", "weak", "willSet", + "Type" ]; } @@ -95,7 +96,9 @@ public function getKeywords(): array */ public function getIdentifierOverrides(): array { - return []; + return [ + 'enum' => 'xenum' + ]; } /** @@ -284,6 +287,11 @@ public function getFiles(): array 'destination' => '/Sources/{{ spec.title | caseUcfirst}}Models/{{ definition.name | caseUcfirst }}.swift', 'template' => '/swift/Sources/Models/Model.swift.twig', ], + [ + 'scope' => 'enum', + 'destination' => '/Sources/{{ spec.title | caseUcfirst}}Enums/{{ enum.name | caseUcfirst }}.swift', + 'template' => '/swift/Sources/Enums/Enum.swift.twig', + ] ]; } @@ -291,29 +299,26 @@ public function getFiles(): array * @param array $parameter * @return string */ - public function getTypeName(array $parameter): string + public function getTypeName(array $parameter, array $spec = []): string { - switch ($parameter['type']) { - case self::TYPE_INTEGER: - return 'Int'; - case self::TYPE_NUMBER: - return 'Double'; - case self::TYPE_STRING: - return 'String'; - case self::TYPE_FILE: - return 'InputFile'; - case self::TYPE_BOOLEAN: - return 'Bool'; - case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { - return '[' . $this->getTypeName($parameter['array']) . ']'; - } - return '[Any]'; - case self::TYPE_OBJECT: - return 'Any'; + if (isset($parameter['enumName'])) { + return ($spec['title'] ?? '') . 'Enums.' . \ucfirst($parameter['enumName']); } - - return $parameter['type']; + if (!empty($parameter['enumValues'])) { + return ($spec['title'] ?? '') . 'Enums.' . \ucfirst($parameter['name']); + } + return match ($parameter['type']) { + self::TYPE_INTEGER => 'Int', + self::TYPE_NUMBER => 'Double', + self::TYPE_STRING => 'String', + self::TYPE_FILE => 'InputFile', + self::TYPE_BOOLEAN => 'Bool', + self::TYPE_ARRAY => (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) + ? '[' . $this->getTypeName($parameter['array']) . ']' + : '[Any]', + self::TYPE_OBJECT => 'Any', + default => $parameter['type'], + }; } /** @@ -456,6 +461,19 @@ public function getFilters(): array new TwigFilter('hasGenericType', function (string $model, array $spec) { return $this->hasGenericType($model, $spec); }), + new TwigFilter('escapeSwiftKeyword', function ($value) { + if (\in_array($value, $this->getKeywords())) { + return "`{$value}`"; + } + return $value; + }), + new TwigFilter('caseEnumKey', function (string $value) { + if (isset($this->getIdentifierOverrides()[$value])) { + $value = $this->getIdentifierOverrides()[$value]; + } + $value = \preg_replace('/[^a-zA-Z0-9]/', '', $value); + return $this->toCamelCase($value); + }), ]; } @@ -476,7 +494,7 @@ protected function getReturnType(array $method, array $spec, string $generic): s return 'Any'; } - $ret = $this->toUpperCaseWords($method['responseModel']); + $ret = $this->toPascalCase($method['responseModel']); if ($this->hasGenericType($method['responseModel'], $spec)) { $ret .= '<' . $generic . '>'; @@ -488,15 +506,15 @@ protected function getReturnType(array $method, array $spec, string $generic): s protected function getModelType(array $definition, array $spec, string $generic): string { if ($this->hasGenericType($definition['name'], $spec)) { - return $this->toUpperCaseWords($definition['name']) . '<' . $generic . '>'; + return $this->toPascalCase($definition['name']) . '<' . $generic . '>'; } - return $this->toUpperCaseWords($definition['name']); + return $this->toPascalCase($definition['name']); } protected function getPropertyType(array $property, array $spec, string $generic): string { if (\array_key_exists('sub_schema', $property)) { - $type = $this->toUpperCaseWords($property['sub_schema']); + $type = $this->toPascalCase($property['sub_schema']); if ($this->hasGenericType($property['sub_schema'], $spec)) { $type .= '<' . $generic . '>'; diff --git a/src/SDK/Language/Web.php b/src/SDK/Language/Web.php index 26ec51136..e29d0d0f1 100644 --- a/src/SDK/Language/Web.php +++ b/src/SDK/Language/Web.php @@ -115,6 +115,11 @@ public function getFiles(): array 'destination' => '.travis.yml', 'template' => 'web/.travis.yml.twig', ], + [ + 'scope' => 'enum', + 'destination' => 'src/enums/{{ enum.name | caseDash }}.ts', + 'template' => 'web/src/enums/enum.ts.twig', + ], ]; } @@ -174,12 +179,18 @@ public function getParamExample(array $param): string public function getTypeName(array $parameter, array $method = []): string { + if (isset($parameter['enumName'])) { + return \ucfirst($parameter['enumName']); + } + if (!empty($parameter['enumValues'])) { + return \ucfirst($parameter['name']); + } switch ($parameter['type']) { case self::TYPE_INTEGER: case self::TYPE_NUMBER: return 'number'; case self::TYPE_ARRAY: - if (!empty($parameter['array']['type'])) { + if (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type'])) { return $this->getTypeName($parameter['array']) . '[]'; } return 'string[]'; @@ -200,15 +211,15 @@ public function getTypeName(array $parameter, array $method = []): string return "Partial>"; } } + break; } - return $parameter['type']; } protected function populateGenerics(string $model, array $spec, array &$generics, bool $skipFirst = false) { if (!$skipFirst && $spec['definitions'][$model]['additionalProperties']) { - $generics[] = $this->toUpperCaseWords($model); + $generics[] = $this->toPascalCase($model); } $properties = $spec['definitions'][$model]['properties']; @@ -257,14 +268,14 @@ public function getReturn(array $method, array $spec): string $ret .= 'Models.'; } - $ret .= $this->toUpperCaseWords($method['responseModel']); + $ret .= $this->toPascalCase($method['responseModel']); $models = []; $this->populateGenerics($method['responseModel'], $spec, $models); $models = array_unique($models); - $models = array_filter($models, fn ($model) => $model != $this->toUpperCaseWords($method['responseModel'])); + $models = array_filter($models, fn ($model) => $model != $this->toPascalCase($method['responseModel'])); if (!empty($models)) { $ret .= '<' . implode(', ', $models) . '>'; @@ -284,9 +295,9 @@ public function getSubSchema(array $property, array $spec): string $generics = []; $this->populateGenerics($property['sub_schema'], $spec, $generics); - $generics = array_filter($generics, fn ($model) => $model != $this->toUpperCaseWords($property['sub_schema'])); + $generics = array_filter($generics, fn ($model) => $model != $this->toPascalCase($property['sub_schema'])); - $ret .= $this->toUpperCaseWords($property['sub_schema']); + $ret .= $this->toPascalCase($property['sub_schema']); if (!empty($generics)) { $ret .= '<' . implode(', ', $generics) . '>'; } @@ -329,6 +340,9 @@ public function getFilters(): array } return implode("\n", $value); }, ['is_safe' => ['html']]), + new TwigFilter('caseEnumKey', function ($value) { + return $this->toPascalCase($value); + }), ]; } } diff --git a/src/SDK/SDK.php b/src/SDK/SDK.php index 73a75ce39..e30450283 100644 --- a/src/SDK/SDK.php +++ b/src/SDK/SDK.php @@ -137,8 +137,8 @@ public function __construct(Language $language, Spec $spec) $this->twig->addFilter(new TwigFilter('caseArray', function ($value) { return (is_array($value)) ? json_encode($value) : '[]'; }, ['is_safe' => ['html']])); - $this->twig->addFilter(new TwigFilter('typeName', function ($value) { - return $this->language->getTypeName($value); + $this->twig->addFilter(new TwigFilter('typeName', function ($value, $spec = []) { + return $this->language->getTypeName($value, $spec); }, ['is_safe' => ['html']])); $this->twig->addFilter(new TwigFilter('paramDefault', function ($value) { return $this->language->getParamDefault($value); @@ -545,6 +545,7 @@ public function generate(string $target): void 'contactURL' => $this->spec->getContactURL(), 'contactEmail' => $this->spec->getContactEmail(), 'services' => $this->spec->getServices(), + 'enums' => $this->spec->getEnumNames(), 'definitions' => $this->spec->getDefinitions(), 'global' => [ 'headers' => $this->spec->getGlobalHeaders(), @@ -634,6 +635,27 @@ public function generate(string $target): void } } break; + case 'enum': + foreach ($this->spec->getServices() as $key => $service) { + $methods = $this->spec->getMethods($key); + + foreach ($methods as $method) { + $parameters = $method['parameters']['all']; + + foreach ($parameters as $parameter) { + // Check if the enum field is defined + if (isset($parameter['enumValues'])) { + $params['enum'] = [ + 'name' => $parameter['enumName'] ?? $parameter['name'], + 'enum' => $parameter['enumValues'], + 'keys' => $parameter['enumKeys'], + ]; + $this->render($template, $destination, $block, $params, $minify); + } + } + } + } + break; } } } diff --git a/src/Spec/Spec.php b/src/Spec/Spec.php index 6ffbbba53..cf22cfa18 100644 --- a/src/Spec/Spec.php +++ b/src/Spec/Spec.php @@ -164,4 +164,11 @@ public function setAttribute($key, $value, $type = self::SET_TYPE_ASSIGN) return $this; } + + /** + * Get EnumNames + * + * @return array + */ + abstract public function getEnumNames(); } diff --git a/src/Spec/Swagger2.php b/src/Spec/Swagger2.php index bf343ea83..db436ac93 100644 --- a/src/Spec/Swagger2.php +++ b/src/Spec/Swagger2.php @@ -221,6 +221,11 @@ public function getMethods($service) } $param['default'] = (is_array($param['default'])) ? json_encode($param['default']) : $param['default']; + if (isset($parameter['enum'])) { + $param['enumValues'] = $parameter['enum']; + $param['enumName'] = $parameter['x-enum-name']; + $param['enumKeys'] = $parameter['x-enum-keys']; + } switch ($parameter['in']) { case 'header': @@ -240,24 +245,31 @@ public function getMethods($service) $bodyRequired = $parameter['schema']['required'] ?? []; foreach ($bodyProperties as $key => $value) { - $param['name'] = $key; - $param['type'] = $value['type'] ?? null; - $param['description'] = $value['description'] ?? ''; - $param['required'] = (in_array($key, $bodyRequired)); - $param['example'] = $value['x-example'] ?? null; - $param['isUploadID'] = $value['x-upload-id'] ?? false; - $param['nullable'] = $value['x-nullable'] ?? false; - $param['array'] = [ + $temp = $param; + $temp['name'] = $key; + $temp['type'] = $value['type'] ?? null; + $temp['description'] = $value['description'] ?? ''; + $temp['required'] = (in_array($key, $bodyRequired)); + $temp['example'] = $value['x-example'] ?? null; + $temp['isUploadID'] = $value['x-upload-id'] ?? false; + $temp['nullable'] = $value['x-nullable'] ?? false; + $temp['array'] = [ 'type' => $value['items']['type'] ?? '', ]; if ($value['type'] === 'object' && is_array($value['default'])) { $value['default'] = (empty($value['default'])) ? new stdClass() : $value['default']; } - $param['default'] = (is_array($value['default']) || $value['default'] instanceof stdClass) ? json_encode($value['default']) : $value['default']; + if (isset($value['enum'])) { + $temp['enumValues'] = $value['enum']; + $temp['enumName'] = $value['x-enum-name']; + $temp['enumKeys'] = $value['x-enum-keys']; + } + + $temp['default'] = (is_array($value['default']) || $value['default'] instanceof stdClass) ? json_encode($value['default']) : $value['default']; - $output['parameters']['body'][] = $param; - $output['parameters']['all'][] = $param; + $output['parameters']['body'][] = $temp; + $output['parameters']['all'][] = $temp; } continue 2; @@ -341,4 +353,25 @@ public function getDefinitions() } return $list; } + + /** + * @return array + */ + public function getEnumNames(): array + { + $list = []; + + foreach ($this->getServices() as $key => $service) { + foreach ($this->getMethods($key) as $method) { + if (isset($method['parameters']) && is_array($method['parameters'])) { + foreach ($method['parameters']['all'] as $parameter) { + if (isset($parameter['enumValues'])) { + $list[] = $parameter['enumName'] ?? $parameter['name']; + } + } + } + } + } + return \array_values(\array_unique($list)); + } } diff --git a/templates/android/docs/java/example.md.twig b/templates/android/docs/java/example.md.twig index 23f797098..a49b67fbb 100644 --- a/templates/android/docs/java/example.md.twig +++ b/templates/android/docs/java/example.md.twig @@ -4,19 +4,37 @@ import {{ sdk.namespace | caseDot }}.coroutines.CoroutineCallback; import {{ sdk.namespace | caseDot }}.models.InputFile; {% endif %} import {{ sdk.namespace | caseDot }}.services.{{ service.name | caseUcfirst }}; +{% set added = [] %} +{% for parameter in method.parameters.all %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +import {{ sdk.namespace | caseDot }}.enums.{{ name | caseUcfirst }}; +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} Client client = new Client(context) -{% if method.auth|length > 0 %} + {%~ if method.auth|length > 0 %} .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint -{% for node in method.auth %} -{% for key,header in node|keys %} - .set{{header | caseUcfirst}}("{{node[header]['x-appwrite']['demo']}}"){% if loop.last %};{% endif %} // {{node[header].description}} -{% endfor %}{% endfor %}{% endif %} + {%~ for node in method.auth %} + {%~ for key,header in node|keys %} + .set{{header | caseUcfirst}}("{{node[header]['x-appwrite']['demo']}}"){% if loop.last %};{% endif %} // {{ node[header].description }} + {%~ endfor %} + {%~ endfor %} + {%~ endif %} {{ service.name | caseUcfirst }} {{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}(client); {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% if method.parameters.all | length == 0 %}new CoroutineCallback<>((result, error) -> { - if (error != null) + if (error != null) { error.printStackTrace(); return; } @@ -25,11 +43,19 @@ Client client = new Client(context) }));{% endif %} {% for parameter in method.parameters.all %} -{% if parameter.required %} - {{ parameter | paramExample }}{% if not loop.last %},{% endif %} - -{% endif %} -{% if loop.last %} + {%~ if parameter.required -%} + {%~ if parameter.enumValues is not empty -%} + {%~ if parameter.enumName is not empty -%} + {%~ set name = parameter.enumName -%} + {%~ else -%} + {%~ set name = parameter.name -%} + {%~ endif %} + {{ name }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}, + {%~ else %} + {{ parameter | paramExample }}, + {%~ endif -%} + {%~ endif -%} + {%~ if loop.last %} new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); @@ -39,5 +65,5 @@ Client client = new Client(context) Log.d("Appwrite", result.toString()); }) ); -{% endif %} +{%- endif %} {% endfor %} \ No newline at end of file diff --git a/templates/android/docs/kotlin/example.md.twig b/templates/android/docs/kotlin/example.md.twig index 8acb6e64a..175ef8038 100644 --- a/templates/android/docs/kotlin/example.md.twig +++ b/templates/android/docs/kotlin/example.md.twig @@ -1,27 +1,56 @@ import {{ sdk.namespace | caseDot }}.Client +import {{ sdk.namespace | caseDot }}.coroutines.CoroutineCallback {% if method.parameters.all | filter((param) => param.type == 'file') | length > 0 %} import {{ sdk.namespace | caseDot }}.models.InputFile {% endif %} import {{ sdk.namespace | caseDot }}.services.{{ service.name | caseUcfirst }} +{% set added = [] %} +{% for parameter in method.parameters.all %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +import {{ sdk.namespace | caseDot }}.enums.{{ name | caseUcfirst }} +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} val client = Client(context) -{% if method.auth|length > 0 %} + {%~ if method.auth|length > 0 %} .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint -{% for node in method.auth %} -{% for key,header in node|keys %} + {%~ for node in method.auth %} + {%~ for key,header in node|keys %} .set{{header | caseUcfirst}}("{{node[header]['x-appwrite']['demo']}}") // {{node[header].description}} -{% endfor %}{% endfor %}{% endif %} + {%~ endfor %} + {%~ endfor %} + {%~ endif %} val {{ service.name | caseCamel }} = {{ service.name | caseUcfirst }}(client) -{% if method.type == 'webAuth' %}{% elseif method.type == 'location' %}val result = {% else %}val response = {% endif %}{{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% if method.parameters.all | length == 0 %}){% endif %} +{% if method.type == 'webAuth' %} +{% elseif method.type == 'location' %} +val result = {%~ else %}val response = {% endif %}{{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% if method.parameters.all | length == 0 %}){% endif %} {% for parameter in method.parameters.all %} -{% if parameter.required %} - {{parameter.name}} = {{ parameter | paramExample }}{% if not loop.last %},{% endif %} - -{% endif %} -{% if loop.last %} + {%~ if parameter.required -%} + {%~ if parameter.enumValues is not empty -%} + {%~ if parameter.enumName is not empty -%} + {%~ set name = parameter.enumName -%} + {%~ else -%} + {%~ set name = parameter.name -%} + {%~ endif %} + {{ parameter.name }} = {{ name }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}, + {%~ else %} + {{ parameter.name }} = {{ parameter | paramExample }}, + {%~ endif -%} + {%~ endif %} + {%~ if loop.last %} ) -{% endif %} +{%- endif %} {% endfor %} \ No newline at end of file diff --git a/templates/android/library/src/main/java/io/appwrite/enums/Enum.kt.twig b/templates/android/library/src/main/java/io/appwrite/enums/Enum.kt.twig new file mode 100644 index 000000000..920642a54 --- /dev/null +++ b/templates/android/library/src/main/java/io/appwrite/enums/Enum.kt.twig @@ -0,0 +1,11 @@ +package {{ sdk.namespace | caseDot }}.enums + +enum class {{ enum.name | caseUcfirst | overrideIdentifier }}(val value: String) { +{% for value in enum.enum %} +{% set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseEnumKey }}("{{value}}"){% if not loop.last %},{% else %};{% endif %} + +{% endfor %} + + override fun toString() = value +} \ No newline at end of file diff --git a/templates/android/library/src/main/java/io/appwrite/services/ServiceTemplate.kt.twig b/templates/android/library/src/main/java/io/appwrite/services/ServiceTemplate.kt.twig index a461b5f91..21628b501 100644 --- a/templates/android/library/src/main/java/io/appwrite/services/ServiceTemplate.kt.twig +++ b/templates/android/library/src/main/java/io/appwrite/services/ServiceTemplate.kt.twig @@ -2,7 +2,12 @@ package {{ sdk.namespace | caseDot }}.services import android.net.Uri import {{ sdk.namespace | caseDot }}.Client +{% if spec.definitions is not empty %} import {{ sdk.namespace | caseDot }}.models.* +{% endif %} +{% if spec.enums is not empty %} +import {{ sdk.namespace | caseDot }}.enums.* +{% endif %} import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.title | caseUcfirst }}Exception import {{ sdk.namespace | caseDot }}.extensions.classOf {% if service.features.webAuth %} @@ -55,7 +60,7 @@ class {{ service.name | caseUcfirst }} : Service { ){% if method.type != "webAuth" %}: {{ method | returnType(spec, sdk.namespace | caseDot) | raw }}{% endif %} { val apiPath = "{{ method.path }}" {%~ for parameter in method.parameters.path %} - .replace("{{ '{' ~ parameter.name | caseCamel ~ '}' }}", {{ parameter.name | caseCamel }}) + .replace("{{ '{' ~ parameter.name | caseCamel ~ '}' }}", {{ parameter.name | caseCamel }}{% if parameter.enumValues is not empty %}.value{% endif %}) {%~ endfor %} val apiParams = mutableMapOf( diff --git a/templates/dart/docs/example.md.twig b/templates/dart/docs/example.md.twig index 5e2afae03..a8e809dd6 100644 --- a/templates/dart/docs/example.md.twig +++ b/templates/dart/docs/example.md.twig @@ -22,7 +22,7 @@ void main() { // Init SDK {% endif %} {% if parameter.required %} - {{ parameter.name | caseCamel | overrideIdentifier }}: {{ parameter | paramExample | replace({'': (parameter.name | caseCamel) }) | raw }}, + {{ parameter.name | caseCamel | overrideIdentifier }}:{% if parameter.enumValues | length > 0 %} {{ parameter.enumName }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseCamel | replace({'-': ''}) }}{% else %}{{ parameter | paramExample | replace({'': (parameter.name | caseCamel) }) | raw }} {% endif %}, {% endif %} {% endfor %}{% if method.parameters.all | length > 0 %} {% endif %}); @@ -32,4 +32,4 @@ void main() { // Init SDK }).catchError((error) { print(error.response); }); -} \ No newline at end of file +}} \ No newline at end of file diff --git a/templates/dart/lib/enums.dart.twig b/templates/dart/lib/enums.dart.twig new file mode 100644 index 000000000..4980d4b5e --- /dev/null +++ b/templates/dart/lib/enums.dart.twig @@ -0,0 +1,6 @@ +/// {{spec.title | caseUcfirst}} Enums +library {{ language.params.packageName }}.enums; + +{% for enum in spec.enums %} +part 'src/enums/{{enum | caseSnake}}.dart'; +{% endfor %} \ No newline at end of file diff --git a/templates/dart/lib/package.dart.twig b/templates/dart/lib/package.dart.twig index 2ff4077c0..648964076 100644 --- a/templates/dart/lib/package.dart.twig +++ b/templates/dart/lib/package.dart.twig @@ -13,6 +13,7 @@ import 'src/service.dart'; import 'src/input_file.dart'; import 'src/upload_progress.dart'; import 'models.dart' as models; +import 'enums.dart' as enums; export 'src/response.dart'; export 'src/client.dart'; diff --git a/templates/dart/lib/services/service.dart.twig b/templates/dart/lib/services/service.dart.twig index 71cba9ccc..7a953bee2 100644 --- a/templates/dart/lib/services/service.dart.twig +++ b/templates/dart/lib/services/service.dart.twig @@ -19,7 +19,7 @@ class {{ service.name | caseUcfirst }} extends Service { {%~ if method.description %} {{ method.description | dartComment }} {% endif %} - {% if method.type == 'location' %}Future{% else %}{% if method.responseModel and method.responseModel != 'any' %}Future{% else %}Future{% endif %}{% endif %} {{ method.name | caseCamel }}({{ _self.method_parameters(method.parameters.all, method.consumes) }}) async { + {% if method.type == 'location' %}Future{% else %}{% if method.responseModel and method.responseModel != 'any' %}Future{% else %}Future{% endif %}{% endif %} {{ method.name | caseCamel | overrideIdentifier }}({{ _self.method_parameters(method.parameters.all, method.consumes) }}) async { final String apiPath = '{{ method.path }}'{% for parameter in method.parameters.path %}.replaceAll('{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}', {{ parameter.name | caseCamel | overrideIdentifier }}){% endfor %}; {% if 'multipart/form-data' in method.consumes %} diff --git a/templates/dart/lib/src/enums/enum.dart.twig b/templates/dart/lib/src/enums/enum.dart.twig new file mode 100644 index 000000000..10ab94833 --- /dev/null +++ b/templates/dart/lib/src/enums/enum.dart.twig @@ -0,0 +1,17 @@ +part of {{ language.params.packageName }}.enums; + +enum {{ enum.name | caseUcfirst | overrideIdentifier }} { + {%~ for value in enum.enum %} + {%~ set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseEnumKey }}(value: '{{ value }}'){% if not loop.last %},{% else %};{% endif %} + + {%~ endfor %} + + const {{ enum.name | caseUcfirst | overrideIdentifier }}({ + required this.value + }); + + final String value; + + String toJson() => value; +} \ No newline at end of file diff --git a/templates/deno/docs/example.md.twig b/templates/deno/docs/example.md.twig index 55f3735ee..13ac81a3c 100644 --- a/templates/deno/docs/example.md.twig +++ b/templates/deno/docs/example.md.twig @@ -19,7 +19,7 @@ client {% endif %} -let promise = {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{ parameter | paramExample }}{% endif %}{% endfor %}); +let promise = {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{% if parameter.enumValues | length > 0%}{{parameter.enumName}}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else%}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %}); promise.then(function (response) { console.log(response); diff --git a/templates/deno/mod.ts.twig b/templates/deno/mod.ts.twig index 2878b6360..fea529ed2 100644 --- a/templates/deno/mod.ts.twig +++ b/templates/deno/mod.ts.twig @@ -8,6 +8,9 @@ import { {{spec.title | caseUcfirst}}Exception } from "./src/exception.ts"; {% for service in spec.services %} import { {{service.name | caseUcfirst}} } from "./src/services/{{service.name | caseDash}}.ts"; {% endfor %} +{% for enum in spec.enums %} +import { {{enum | caseUcfirst}} } from "./src/enums/{{enum | caseDash}}.ts"; +{% endfor %} export { Client, @@ -20,6 +23,9 @@ export { {% for service in spec.services %} {{service.name | caseUcfirst}}, {% endfor %} +{% for enum in spec.enums %} + {{enum | caseUcfirst}}, +{% endfor %} }; export type { Models } from "./src/models.d.ts"; diff --git a/templates/deno/src/enums/enum.ts.twig b/templates/deno/src/enums/enum.ts.twig new file mode 100644 index 000000000..34724aba0 --- /dev/null +++ b/templates/deno/src/enums/enum.ts.twig @@ -0,0 +1,6 @@ +export enum {{ enum.name | caseUcfirst | overrideIdentifier }} { + {%~ for value in enum.enum %} + {%~ set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseUcfirst | replace({'-': ''}) }} = '{{ value }}', + {%~ endfor %} +} \ No newline at end of file diff --git a/templates/deno/src/services/service.ts.twig b/templates/deno/src/services/service.ts.twig index dbaecfca6..9e3b6da70 100644 --- a/templates/deno/src/services/service.ts.twig +++ b/templates/deno/src/services/service.ts.twig @@ -31,6 +31,22 @@ import { Payload, Client } from '../client.ts'; import { InputFile } from '../inputFile.ts'; import { AppwriteException } from '../exception.ts'; import type { Models } from '../models.d.ts'; +{% set added = [] %} +{% for method in service.methods %} +{% for parameter in method.parameters.all %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +import { {{ name | caseUcfirst }} } from '../enums/{{ name | caseDash }}.ts'; +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endfor %} +{% endfor %} export type UploadProgress = { $id: string; @@ -128,7 +144,11 @@ export class {{ service.name | caseUcfirst }} extends Service { } const start = ((currentChunk - 1) * Client.CHUNK_SIZE); - const end = start + currentPosition; + let end = start + currentPosition; + + if (end === size) { + end -= 1; + } if(!lastUpload || currentChunk !== 1) { apiHeaders['content-range'] = 'bytes ' + start + '-' + end + '/' + size; diff --git a/templates/dotnet/base/params.twig b/templates/dotnet/base/params.twig index 0918c9d65..482ae36ed 100644 --- a/templates/dotnet/base/params.twig +++ b/templates/dotnet/base/params.twig @@ -1,6 +1,6 @@ {% import 'dotnet/base/utils.twig' as utils %} {%~ for parameter in method.parameters.path %} - .Replace("{{ '{' ~ parameter.name | caseCamel ~ '}' }}", {{ parameter.name | caseCamel | escapeKeyword }}){% if loop.last %};{% endif %} + .Replace("{{ '{' ~ parameter.name | caseCamel ~ '}' }}", {{ parameter.name | caseCamel | escapeKeyword }}{% if parameter.enumValues is not empty %}.Value{% endif %}){% if loop.last %};{% endif %} {%~ endfor %} diff --git a/templates/dotnet/docs/example.md.twig b/templates/dotnet/docs/example.md.twig index 2ce25f701..51b6c602c 100644 --- a/templates/dotnet/docs/example.md.twig +++ b/templates/dotnet/docs/example.md.twig @@ -1,6 +1,9 @@ using {{ spec.title | caseUcfirst }}; using {{ spec.title | caseUcfirst }}.Services; using {{ spec.title | caseUcfirst }}.Models; +{% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}{% endif %} +using {{ spec.title | caseUcfirst }}.Enums; +{% endif %}{% endfor %} var client = new Client() {% if method.auth|length > 0 %} @@ -15,4 +18,4 @@ var {{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}(client {% if method.method != 'delete' %}{% if method.type == 'location' %}byte[]{% else %}{{ method.responseModel | caseUcfirst | overrideIdentifier }}{% endif %} result = {% endif %}await {{ service.name | caseCamel }}.{{ method.name | caseUcfirst }}({% if method.parameters.all | length == 0 %});{% endif %} {% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %},{% endif %} - {{ parameter.name }}: {{ parameter | paramExample }}{% endif %}{% endfor %}{% if method.parameters.all | length > 0 %});{% endif %} + {{ parameter.name }}: {% if parameter.enumValues | length > 0%}{{ parameter.enumName }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else %}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %}{% if method.parameters.all | length > 0 %});{% endif %} diff --git a/templates/dotnet/src/Appwrite/Appwrite.csproj.twig b/templates/dotnet/src/Appwrite/Appwrite.csproj.twig index 74673a1eb..9d5539f32 100644 --- a/templates/dotnet/src/Appwrite/Appwrite.csproj.twig +++ b/templates/dotnet/src/Appwrite/Appwrite.csproj.twig @@ -20,7 +20,7 @@ - + diff --git a/templates/dotnet/src/Appwrite/Client.cs.twig b/templates/dotnet/src/Appwrite/Client.cs.twig index 0f11ee45f..df6e01abf 100644 --- a/templates/dotnet/src/Appwrite/Client.cs.twig +++ b/templates/dotnet/src/Appwrite/Client.cs.twig @@ -10,6 +10,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; +using {{ spec.title | caseUcfirst }}.Converters; using {{ spec.title | caseUcfirst }}.Extensions; using {{ spec.title | caseUcfirst }}.Models; @@ -34,7 +35,8 @@ namespace {{ spec.title | caseUcfirst }} ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List { - new StringEnumConverter() + new StringEnumConverter(new CamelCaseNamingStrategy()), + new ValueClassConverter() } }; @@ -44,7 +46,8 @@ namespace {{ spec.title | caseUcfirst }} ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List { - new StringEnumConverter() + new StringEnumConverter(new CamelCaseNamingStrategy()), + new ValueClassConverter() } }; @@ -326,7 +329,7 @@ namespace {{ spec.title | caseUcfirst }} parameters = new Dictionary() ); var chunksUploaded = (long)current["chunksUploaded"]; - offset = Math.Min(chunksUploaded * ChunkSize, size); + offset = chunksUploaded * ChunkSize; } while (offset < size) @@ -342,7 +345,7 @@ namespace {{ spec.title | caseUcfirst }} case "bytes": buffer = ((byte[])input.Data) .Skip((int)offset) - .Take((int)Math.Min(size - offset, ChunkSize)) + .Take((int)Math.Min(size - offset, ChunkSize - 1)) .ToArray(); break; } diff --git a/templates/dotnet/src/Appwrite/Converters/ValueClassConverter.cs.twig b/templates/dotnet/src/Appwrite/Converters/ValueClassConverter.cs.twig new file mode 100644 index 000000000..8c6a46714 --- /dev/null +++ b/templates/dotnet/src/Appwrite/Converters/ValueClassConverter.cs.twig @@ -0,0 +1,38 @@ +using System; +using {{ spec.title | caseUcfirst }}.Enums; +using Newtonsoft.Json; + +namespace {{ spec.title | caseUcfirst }}.Converters +{ + public class ValueClassConverter : JsonConverter { + + public override bool CanConvert(Type objectType) + { + return typeof(IEnum).IsAssignableFrom(objectType); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var value = (string)reader.Value; + var constructor = objectType.GetConstructor(new[] { typeof(string) }); + var obj = constructor.Invoke(new object[] { value }); + + return Convert.ChangeType(obj, objectType); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var type = value.GetType(); + var property = type.GetProperty(nameof(IEnum.Value)); + var propertyValue = property.GetValue(value); + + if (propertyValue == null) + { + writer.WriteNull(); + return; + } + + writer.WriteValue(propertyValue); + } + } +} diff --git a/templates/dotnet/src/Appwrite/Enums/Enum.cs.twig b/templates/dotnet/src/Appwrite/Enums/Enum.cs.twig new file mode 100644 index 000000000..6720ce59b --- /dev/null +++ b/templates/dotnet/src/Appwrite/Enums/Enum.cs.twig @@ -0,0 +1,19 @@ +using System; + +namespace {{ spec.title | caseUcfirst }}.Enums +{ + public class {{ enum.name | caseUcfirst | overrideIdentifier }} : IEnum + { + public string Value { get; private set; } + + public {{ enum.name | caseUcfirst | overrideIdentifier }}(string value) + { + Value = value; + } + + {%~ for value in enum.enum %} + {%~ set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + public static {{ enum.name | caseUcfirst | overrideIdentifier }} {{ key | caseEnumKey }} => new {{ enum.name | caseUcfirst | overrideIdentifier }}("{{ value }}"); + {%~ endfor %} + } +} diff --git a/templates/dotnet/src/Appwrite/Enums/IEnum.cs.twig b/templates/dotnet/src/Appwrite/Enums/IEnum.cs.twig new file mode 100644 index 000000000..5d7744d12 --- /dev/null +++ b/templates/dotnet/src/Appwrite/Enums/IEnum.cs.twig @@ -0,0 +1,9 @@ +using System; + +namespace {{ spec.title | caseUcfirst }}.Enums +{ + public interface IEnum + { + public string Value { get; } + } +} diff --git a/templates/dotnet/src/Appwrite/Services/ServiceTemplate.cs.twig b/templates/dotnet/src/Appwrite/Services/ServiceTemplate.cs.twig index 732d36ac7..81d47cfa2 100644 --- a/templates/dotnet/src/Appwrite/Services/ServiceTemplate.cs.twig +++ b/templates/dotnet/src/Appwrite/Services/ServiceTemplate.cs.twig @@ -4,7 +4,12 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +{% if spec.definitions is not empty %} using {{ spec.title | caseUcfirst }}.Models; +{% endif %} +{% if spec.enums is not empty %} +using {{ spec.title | caseUcfirst }}.Enums; +{% endif %} namespace {{ spec.title | caseUcfirst }}.Services { diff --git a/templates/flutter/docs/example.md.twig b/templates/flutter/docs/example.md.twig index db87c778c..8bb04a23a 100644 --- a/templates/flutter/docs/example.md.twig +++ b/templates/flutter/docs/example.md.twig @@ -23,7 +23,7 @@ void main() { // Init SDK {% endif %} {% if parameter.required %} - {{ parameter.name | caseCamel }}: {{ parameter | paramExample }}, + {{ parameter.name | caseCamel | overrideIdentifier}}:{% if parameter.enumValues | length > 0%} {{parameter.enumName}}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}.value{% else %}{{ parameter | paramExample}} {% endif %}, {% endif %} {% endfor %}{% if method.parameters.all | length > 0 %} {% endif %}).then((bytes) { final file = File('path_to_file/filename.ext'); @@ -40,7 +40,7 @@ FutureBuilder( {% endif %} {% if parameter.required %} - {{ parameter.name | caseCamel | overrideIdentifier }}: {{ parameter | paramExample }}, + {{ parameter.name | caseCamel | overrideIdentifier}}:{% if parameter.enumValues | length > 0%} {{parameter.enumName}}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}.value{% else %}{{ parameter | paramExample}} {% endif %}, {% endif %} {% endfor %}{% if method.parameters.all | length > 0 %} {% endif %} ), //works for both public file and private file, for private files you need to be logged in @@ -58,7 +58,7 @@ FutureBuilder( {% endif %} {% if parameter.required %} - {{ parameter.name | caseCamel }}: {{ parameter | paramExample }}, + {{ parameter.name | caseCamel | overrideIdentifier}}:{% if parameter.enumValues | length > 0%} {{parameter.enumName}}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}.value{% else %}{{ parameter | paramExample}} {% endif %}, {% endif %} {% endfor %}{% if method.parameters.all | length > 0 %} {% endif %}); diff --git a/templates/flutter/lib/package.dart.twig b/templates/flutter/lib/package.dart.twig index 9d92197b1..919d34d5c 100644 --- a/templates/flutter/lib/package.dart.twig +++ b/templates/flutter/lib/package.dart.twig @@ -11,6 +11,7 @@ import 'src/enums.dart'; import 'src/service.dart'; import 'src/input_file.dart'; import 'models.dart' as models; +import 'enums.dart' as enums; import 'src/upload_progress.dart'; export 'src/response.dart'; diff --git a/templates/flutter/lib/services/service.dart.twig b/templates/flutter/lib/services/service.dart.twig index 03be8528e..d2df0bc8d 100644 --- a/templates/flutter/lib/services/service.dart.twig +++ b/templates/flutter/lib/services/service.dart.twig @@ -20,7 +20,7 @@ class {{ service.name | caseUcfirst }} extends Service { {%~ if method.description %} {{ method.description|dartComment }} {% endif %} - {% if method.type == 'webAuth' %}Future{% elseif method.type == 'location' %}Future{% else %}{% if method.responseModel and method.responseModel != 'any' %}Future{% else %}Future{% endif %}{% endif %} {{ method.name | caseCamel }}({{ _self.method_parameters(method.parameters.all, method.consumes) }}) async { + {% if method.type == 'webAuth' %}Future{% elseif method.type == 'location' %}Future{% else %}{% if method.responseModel and method.responseModel != 'any' %}Future{% else %}Future{% endif %}{% endif %} {{ method.name | caseCamel | overrideIdentifier }}({{ _self.method_parameters(method.parameters.all, method.consumes) }}) async { {% if method.parameters.path | length > 0 %}final{% else %}const{% endif %} String apiPath = '{{ method.path }}'{% for parameter in method.parameters.path %}.replaceAll('{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}', {{ parameter.name | caseCamel | overrideIdentifier }}){% endfor %}; {% if 'multipart/form-data' in method.consumes %} diff --git a/templates/kotlin/docs/java/example.md.twig b/templates/kotlin/docs/java/example.md.twig index 75508a1ff..faef6d972 100644 --- a/templates/kotlin/docs/java/example.md.twig +++ b/templates/kotlin/docs/java/example.md.twig @@ -4,6 +4,22 @@ import {{ sdk.namespace | caseDot }}.coroutines.CoroutineCallback; import {{ sdk.namespace | caseDot }}.models.InputFile; {% endif %} import {{ sdk.namespace | caseDot }}.services.{{ service.name | caseUcfirst }}; +{% set added = [] %} +{% for parameter in method.parameters.all %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +import {{ sdk.namespace | caseDot }}.enums.{{ name | caseUcfirst }}; +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} Client client = new Client() {% if method.auth|length > 0 %} @@ -26,7 +42,7 @@ Client client = new Client() {% for parameter in method.parameters.all %} {% if parameter.required %} - {{ parameter | paramExample }}{% if not loop.last %},{% endif %} + {% if parameter.enumValues | length > 0%}{{ parameter.enumName }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else%}{{ parameter | paramExample }}{% endif %}{% if not loop.last %},{% endif %} {% endif %} {% if loop.last %} diff --git a/templates/kotlin/docs/kotlin/example.md.twig b/templates/kotlin/docs/kotlin/example.md.twig index 8acb6e64a..c5703ac3d 100644 --- a/templates/kotlin/docs/kotlin/example.md.twig +++ b/templates/kotlin/docs/kotlin/example.md.twig @@ -1,10 +1,27 @@ import {{ sdk.namespace | caseDot }}.Client +import {{ sdk.namespace | caseDot }}.coroutines.CoroutineCallback {% if method.parameters.all | filter((param) => param.type == 'file') | length > 0 %} import {{ sdk.namespace | caseDot }}.models.InputFile {% endif %} import {{ sdk.namespace | caseDot }}.services.{{ service.name | caseUcfirst }} +{% set added = [] %} +{% for parameter in method.parameters.all %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +import {{ sdk.namespace | caseDot }}.enums.{{ name | caseUcfirst }} +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} -val client = Client(context) +val client = Client() {% if method.auth|length > 0 %} .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint {% for node in method.auth %} @@ -18,7 +35,7 @@ val {{ service.name | caseCamel }} = {{ service.name | caseUcfirst }}(client) {% for parameter in method.parameters.all %} {% if parameter.required %} - {{parameter.name}} = {{ parameter | paramExample }}{% if not loop.last %},{% endif %} + {{parameter.name}} = {% if parameter.enumValues | length > 0 %} {{ parameter.enumName }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else%}{{ parameter | paramExample }}{% endif %}{% if not loop.last %},{% endif %} {% endif %} {% if loop.last %} diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/enums/Enum.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/enums/Enum.kt.twig new file mode 100644 index 000000000..920642a54 --- /dev/null +++ b/templates/kotlin/src/main/kotlin/io/appwrite/enums/Enum.kt.twig @@ -0,0 +1,11 @@ +package {{ sdk.namespace | caseDot }}.enums + +enum class {{ enum.name | caseUcfirst | overrideIdentifier }}(val value: String) { +{% for value in enum.enum %} +{% set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseEnumKey }}("{{value}}"){% if not loop.last %},{% else %};{% endif %} + +{% endfor %} + + override fun toString() = value +} \ No newline at end of file diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig index 5fb0f8069..d87f79faa 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig @@ -1,7 +1,12 @@ package {{ sdk.namespace | caseDot }}.services import {{ sdk.namespace | caseDot }}.Client +{% if spec.definitions is not empty %} import {{ sdk.namespace | caseDot }}.models.* +{% endif %} +{% if spec.enums is not empty %} +import {{ sdk.namespace | caseDot }}.enums.* +{% endif %} import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.title | caseUcfirst }}Exception import {{ sdk.namespace | caseDot }}.extensions.classOf import okhttp3.Cookie @@ -51,7 +56,7 @@ class {{ service.name | caseUcfirst }} : Service { ): {{ method | returnType(spec, sdk.namespace | caseDot) | raw }} { val apiPath = "{{ method.path }}" {%~ for parameter in method.parameters.path %} - .replace("{{ '{' ~ parameter.name | caseCamel ~ '}' }}", {{ parameter.name | caseCamel }}) + .replace("{{ '{' ~ parameter.name | caseCamel ~ '}' }}", {{ parameter.name | caseCamel }}{% if parameter.enumValues is not empty %}.value{% endif %}) {%~ endfor %} val apiParams = mutableMapOf( diff --git a/templates/node/docs/example.md.twig b/templates/node/docs/example.md.twig index 9c0a7a260..3b79fbb21 100644 --- a/templates/node/docs/example.md.twig +++ b/templates/node/docs/example.md.twig @@ -6,7 +6,7 @@ const fs = require('fs'); // Init SDK const client = new sdk.Client(); -const {{ service.name | caseCamel }} = new sdk.{{service.name | caseUcfirst}}(client{% if service.globalParams | length %}{% for parameter in service.globalParams %}, {{ parameter | paramExample }}{% endfor %}{% endif %}); +const {{ service.name | caseCamel }} = new sdk.{{service.name | caseUcfirst}}(client); {% if method.auth|length > 0 %} client @@ -18,7 +18,7 @@ client {% endfor %}; {% endif %} -const promise = {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{ parameter | paramExample }}{% endif %}{% endfor %}); +const promise = {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{% if parameter.enumValues | length > 0%}sdk.{{ parameter.enumName }}.{{(parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else %}{{ parameter | paramExample}}{% endif %}{% endif %}{% endfor %}); promise.then(function (response) { console.log(response); diff --git a/templates/node/index.js.twig b/templates/node/index.js.twig index b82be2323..7953c18f7 100644 --- a/templates/node/index.js.twig +++ b/templates/node/index.js.twig @@ -8,6 +8,9 @@ const {{spec.title | caseUcfirst}}Exception = require('./lib/exception.js'); {% for service in spec.services %} const {{service.name | caseUcfirst}} = require('./lib/services/{{service.name | caseDash}}.js'); {% endfor %} +{% for enum in spec.enums %} +const {{enum | caseUcfirst}} = require("./lib/enums/{{enum | caseDash}}.js"); +{% endfor %} module.exports = { Client, @@ -19,5 +22,7 @@ module.exports = { {{spec.title | caseUcfirst}}Exception, {% for service in spec.services %} {{service.name | caseUcfirst}}, +{% endfor %}{% for enum in spec.enums %} + {{ enum | caseUcfirst }}, {% endfor %} }; diff --git a/templates/node/lib/client.js.twig b/templates/node/lib/client.js.twig index c3b8130e5..0f68e1c8b 100644 --- a/templates/node/lib/client.js.twig +++ b/templates/node/lib/client.js.twig @@ -18,24 +18,24 @@ class Client { 'x-sdk-platform': '{{ sdk.platform }}', 'x-sdk-language': '{{ language.name | caseLower }}', 'x-sdk-version': '{{ sdk.version }}', -{% for key,header in spec.global.defaultHeaders %} + {%~ for key,header in spec.global.defaultHeaders %} '{{key}}' : '{{header}}', -{% endfor %} + {%~ endfor %} }; this.selfSigned = false; } -{% for header in spec.global.headers %} + {%~ for header in spec.global.headers %} /** * Set {{header.key | caseUcfirst}} * -{% if header.description %} + {%~ if header.description %} * {{header.description}} * -{% endif %} + {%~ endif %} * @param {string} {{header.key | caseLower}} * - * @return self + * @return Client */ set{{header.key | caseUcfirst}}({{header.key | caseLower}}) { this.addHeader('{{header.name}}', {{header.key | caseLower}}); @@ -43,7 +43,7 @@ class Client { return this; } -{% endfor %} + {%~ endfor %} /** * Set self signed. * @@ -127,6 +127,7 @@ class Client { } try { let response = await axios(options); + return response.data; } catch(error) { if('response' in error && error.response !== undefined) { diff --git a/templates/node/lib/enums/enum.js.twig b/templates/node/lib/enums/enum.js.twig new file mode 100644 index 000000000..8d7fd4652 --- /dev/null +++ b/templates/node/lib/enums/enum.js.twig @@ -0,0 +1,9 @@ +const {{ enum.name | caseUcfirst | overrideIdentifier }} = { +{% for value in enum.enum %} +{% set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseCamel | replace({'-': '',' ': ''})}}: '{{value}}' {% if not loop.last %},{% endif %} + +{% endfor %} +} + +module.exports = {{ enum.name | caseUcfirst | overrideIdentifier }}; \ No newline at end of file diff --git a/templates/php/docs/example.md.twig b/templates/php/docs/example.md.twig index 8936a48d3..8cabc50b3 100644 --- a/templates/php/docs/example.md.twig +++ b/templates/php/docs/example.md.twig @@ -5,6 +5,22 @@ use {{ spec.title | caseUcfirst }}\Client; use {{ spec.title | caseUcfirst }}\InputFile; {% endif %} use {{ spec.title | caseUcfirst }}\Services\{{ service.name | caseUcfirst }}; +{% set added = [] %} +{% for parameter in method.parameters.all %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +use {{ spec.title | caseUcfirst }}\Enums\{{parameter.enumName | caseUcfirst}}; +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} $client = new Client(); @@ -18,6 +34,6 @@ $client {% endfor %}; {% endif %} -${{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}($client{% if service.globalParams | length %}{% for parameter in service.globalParams %}, {{ parameter | paramExample }}{% endfor %}{% endif %}); +${{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}($client); -$result = ${{ service.name | caseCamel }}->{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{ parameter | paramExample }}{% endif %}{% endfor %}); \ No newline at end of file +$result = ${{ service.name | caseCamel }}->{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{% if parameter.enumValues | length > 0%}{{ parameter.enumName }}::{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}(){% else%}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %}); \ No newline at end of file diff --git a/templates/php/src/Enums/Enum.php.twig b/templates/php/src/Enums/Enum.php.twig new file mode 100644 index 000000000..08f74c840 --- /dev/null +++ b/templates/php/src/Enums/Enum.php.twig @@ -0,0 +1,41 @@ +value = $value; + } + + public function __toString(): string + { + return $this->value; + } + + public function jsonSerialize(): string + { + return $this->value; + } + +{% for value in enum.enum %} +{% set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + public static function {{ key | caseEnumKey }}(): {{ enum.name | caseUcfirst | overrideIdentifier}} + { + if (!isset(self::${{ key | caseEnumKey }})) { + self::${{ key | caseEnumKey }} = new {{ enum.name | caseUcfirst | overrideIdentifier }}('{{ value }}'); + } + return self::${{ key | caseEnumKey }}; + } +{% endfor %} +} \ No newline at end of file diff --git a/templates/php/src/Services/Service.php.twig b/templates/php/src/Services/Service.php.twig index 73b9c42c8..2261d6067 100644 --- a/templates/php/src/Services/Service.php.twig +++ b/templates/php/src/Services/Service.php.twig @@ -6,6 +6,22 @@ use {{ spec.title | caseUcfirst }}\{{spec.title | caseUcfirst}}Exception; use {{ spec.title | caseUcfirst }}\Client; use {{ spec.title | caseUcfirst }}\Service; use {{ spec.title | caseUcfirst }}\InputFile; +{% set added = [] %} +{% for method in service.methods %} +{% for parameter in method.parameters.all %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +use {{ spec.title | caseUcfirst }}\Enums\{{ name | caseUcfirst }}; +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endfor %} +{% endfor %} class {{ service.name | caseUcfirst }} extends Service { @@ -23,13 +39,13 @@ class {{ service.name | caseUcfirst }} extends Service * {% endif %} {% for parameter in method.parameters.all %} - * @param {{ parameter | typeName }}${{ parameter.name | caseCamel | escapeKeyword }} + * @param {{ parameter | typeName }} ${{ parameter.name | caseCamel | escapeKeyword }} {% endfor %} * @throws {{spec.title | caseUcfirst}}Exception * @return {{ method | getReturn }} */ - public function {{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{{ parameter | typeName }}${{ parameter.name | caseCamel | escapeKeyword }}{% if not parameter.required %} = null{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% if 'multipart/form-data' in method.consumes %}, callable $onProgress = null{% endif %}): {{ method | getReturn }} + public function {{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{{ parameter | typeName }} ${{ parameter.name | caseCamel | escapeKeyword }}{% if not parameter.required %} = null{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% if 'multipart/form-data' in method.consumes %}, callable $onProgress = null{% endif %}): {{ method | getReturn }} { $apiPath = str_replace([{% for parameter in method.parameters.path %}'{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}'{% if not loop.last %}, {% endif %}{% endfor %}], [{% for parameter in method.parameters.path %}${{ parameter.name | caseCamel | escapeKeyword }}{% if not loop.last %}, {% endif %}{% endfor %}], '{{ method.path }}'); diff --git a/templates/python/docs/example.md.twig b/templates/python/docs/example.md.twig index aa291a705..88661d97f 100644 --- a/templates/python/docs/example.md.twig +++ b/templates/python/docs/example.md.twig @@ -2,7 +2,22 @@ from {{ spec.title | caseSnake }}.client import Client {% if method.parameters.all | filter((param) => param.type == 'file') | length > 0 %} from {{ spec.title | caseSnake }}.input_file import InputFile {% endif %} -from {{ spec.title | caseSnake }}.services.{{ service.name | caseSnake }} import {{ service.name | caseUcfirst }} +{% set added = [] %} +{% for parameter in method.parameters.all %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +from {{ spec.title | caseUcfirst }}.enums import {{parameter.enumName | caseUcfirst}} +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} client = Client() @@ -16,6 +31,6 @@ client = Client() {% endfor %}) {% endif %} -{{ service.name | caseSnake }} = {{ service.name | caseUcfirst }}(client{% if service.globalParams | length %}{% for parameter in service.globalParams %}, {{ parameter | paramExample }}{% endfor %}{% endif %}) +{{ service.name | caseSnake }} = {{ service.name | caseUcfirst }}(client) -result = {{ service.name | caseSnake }}.{{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{ parameter | paramExample }}{% endif %}{% endfor %}) +result = {{ service.name | caseSnake }}.{{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{% if parameter.enumValues | length > 0 %}{{ parameter.enumName }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else %}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %}) diff --git a/templates/python/package/client.py.twig b/templates/python/package/client.py.twig index 48ed835a4..db5e74799 100644 --- a/templates/python/package/client.py.twig +++ b/templates/python/package/client.py.twig @@ -1,8 +1,10 @@ import io -import requests +import json import os +import requests from .input_file import InputFile from .exception import {{spec.title | caseUcfirst}}Exception +from .encoders.value_class_encoder import ValueClassEncoder class Client: def __init__(self): @@ -53,7 +55,6 @@ class Client: params = {k: v for k, v in params.items() if v is not None} # Remove None values from params dictionary data = {} - json = {} files = {} stringify = False @@ -64,8 +65,7 @@ class Client: params = {} if headers['content-type'].startswith('application/json'): - json = data - data = {} + data = json.dumps(data, cls=ValueClassEncoder) if headers['content-type'].startswith('multipart/form-data'): del headers['content-type'] @@ -74,14 +74,14 @@ class Client: if isinstance(data[key], InputFile): files[key] = (data[key].filename, data[key].data) del data[key] + data = self.flatten(data, stringify=stringify) response = None try: response = requests.request( # call method dynamically https://stackoverflow.com/a/4246075/2299554 method=method, url=self._endpoint + path, params=self.flatten(params, stringify=stringify), - data=self.flatten(data), - json=json, + data=data, files=files, headers=headers, verify=(not self._self_signed), diff --git a/templates/python/package/encoders/value_class_encoder.py.twig b/templates/python/package/encoders/value_class_encoder.py.twig new file mode 100644 index 000000000..bc84aa453 --- /dev/null +++ b/templates/python/package/encoders/value_class_encoder.py.twig @@ -0,0 +1,13 @@ +import json +{%~ for enum in spec.enums %} +from ..enums.{{ enum | caseSnake }} import {{ enum | caseUcfirst | overrideIdentifier }} +{%~ endfor %} + +class ValueClassEncoder(json.JSONEncoder): + def default(self, o): + {%~ for enum in spec.enums %} + if isinstance(o, {{ enum | caseUcfirst | overrideIdentifier }}): + return o.value + + {%~ endfor %} + return super().default(o) \ No newline at end of file diff --git a/templates/python/package/enums/enum.py.twig b/templates/python/package/enums/enum.py.twig new file mode 100644 index 000000000..e8883e914 --- /dev/null +++ b/templates/python/package/enums/enum.py.twig @@ -0,0 +1,7 @@ +from enum import Enum + +class {{ enum.name | caseUcfirst | overrideIdentifier }}(Enum): +{% for value in enum.enum %} +{% set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseUpper | replace({'-': '',' ':'_', '(': '', ')': '', '.': ''})}} = "{{ value }}" +{% endfor %} \ No newline at end of file diff --git a/templates/ruby/docs/example.md.twig b/templates/ruby/docs/example.md.twig index ed2ef5313..560d0c416 100644 --- a/templates/ruby/docs/example.md.twig +++ b/templates/ruby/docs/example.md.twig @@ -1,6 +1,17 @@ require '{{ spec.title }}' include {{ spec.title | caseUcfirst }} +{% set break = false %} +{% for parameter in method.parameters.all %} +{% if not break %} +{% if method == parameter.required %} +{% if parameter.enumValues is not empty %} +include {{ spec.title | caseUcfirst }}::Enums +{% set break = true %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} client = Client.new .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint @@ -10,8 +21,8 @@ client = Client.new {% endfor %} {% endfor %} -{{ service.name | caseSnake }} = {{ service.name | caseUcfirst }}.new(client{% if service.globalParams | length %}{% for parameter in service.globalParams %}, {{parameter.name | caseSnake}}:{{ parameter | paramExample }}{% endfor %}{% endif %}) +{{ service.name | caseSnake }} = {{ service.name | caseUcfirst }}.new(client) -response = {{ service.name | caseSnake }}.{{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{parameter.name|caseSnake}}: {% if parameter.type == 'file' %}{{ parameter | paramExample }}{% else %}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %}) +response = {{ service.name | caseSnake }}.{{ method.name | caseSnake }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{parameter.name|caseSnake}}: {% if parameter.type == 'file' %}{{ parameter | paramExample }}{% else %}{% if parameter.enumValues | length > 0%}{{ parameter.enumName }}::{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else %}{{ parameter | paramExample }}{% endif %}{% endif %}{% endif %}{% endfor %}) puts response.inspect \ No newline at end of file diff --git a/templates/ruby/lib/container.rb.twig b/templates/ruby/lib/container.rb.twig index 688d54357..7675b688c 100644 --- a/templates/ruby/lib/container.rb.twig +++ b/templates/ruby/lib/container.rb.twig @@ -16,6 +16,10 @@ require_relative '{{ spec.title | caseSnake }}/id' require_relative '{{ spec.title | caseSnake }}/models/{{ defintion.name | caseSnake }}' {% endfor %} +{% for enum in spec.enums %} +require_relative '{{ spec.title | caseSnake }}/enums/{{ enum | caseSnake }}' +{% endfor %} + {% for service in spec.services %} require_relative '{{ spec.title | caseSnake }}/services/{{ service.name | caseSnake }}' {% endfor %} \ No newline at end of file diff --git a/templates/ruby/lib/container/client.rb.twig b/templates/ruby/lib/container/client.rb.twig index 4b4892889..e99d30c94 100644 --- a/templates/ruby/lib/container/client.rb.twig +++ b/templates/ruby/lib/container/client.rb.twig @@ -170,7 +170,7 @@ module {{ spec.title | caseUcfirst }} offset += @chunk_size if defined? result['$id'] - headers['x-{{ spec.title }}-id'] = result['$id'] + headers['x-{{ spec.title | caseLower }}-id'] = result['$id'] end on_progress.call({ diff --git a/templates/ruby/lib/container/enums/enum.rb.twig b/templates/ruby/lib/container/enums/enum.rb.twig new file mode 100644 index 000000000..c640146e4 --- /dev/null +++ b/templates/ruby/lib/container/enums/enum.rb.twig @@ -0,0 +1,10 @@ +module {{ spec.title | caseUcfirst }} + module Enums + module {{ enum.name | caseUcfirst | overrideIdentifier }} + {%~ for value in enum.enum %} + {%~ set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseUpper | replace({'-': '_', ' ':'_', '(': '', ')': '', '.': ''}) }} = '{{ value }}' + {%~ endfor %} + end + end +end \ No newline at end of file diff --git a/templates/swift/Package.swift.twig b/templates/swift/Package.swift.twig index 0204ec6f2..07320adee 100644 --- a/templates/swift/Package.swift.twig +++ b/templates/swift/Package.swift.twig @@ -13,7 +13,12 @@ let package = Package( products: [ .library( name: "{{spec.title | caseUcfirst}}", - targets: ["{{spec.title | caseUcfirst}}", "{{spec.title | caseUcfirst}}Models", "JSONCodable"] + targets: [ + "{{spec.title | caseUcfirst}}", + "{{spec.title | caseUcfirst}}Enums", + "{{spec.title | caseUcfirst}}Models", + "JSONCodable" + ] ), ], dependencies: [ @@ -26,16 +31,28 @@ let package = Package( dependencies: [ .product(name: "AsyncHTTPClient", package: "async-http-client"), .product(name: "NIOWebSocket", package: "swift-nio"), + {%~ if spec.definitions is not empty %} "{{spec.title | caseUcfirst}}Models", + {%~ endif %} + {%~ if spec.enums is not empty %} + "{{spec.title | caseUcfirst}}Enums", + {%~ endif %} "JSONCodable" ] ), + {%~ if spec.definitions is not empty %} .target( name: "{{spec.title | caseUcfirst}}Models", dependencies: [ "JSONCodable" ] ), + {%~ endif %} + {%~ if spec.enums is not empty %} + .target( + name: "{{spec.title | caseUcfirst}}Enums" + ), + {%~ endif %} .target( name: "JSONCodable" ), diff --git a/templates/swift/Sources/Client.swift.twig b/templates/swift/Sources/Client.swift.twig index 8be157d3a..434a4837a 100644 --- a/templates/swift/Sources/Client.swift.twig +++ b/templates/swift/Sources/Client.swift.twig @@ -25,10 +25,10 @@ open class Client { "x-sdk-language": "{{ language.name | caseLower }}", "x-sdk-version": "{{ sdk.version }}"{% if spec.global.defaultHeaders | length > 0 %},{% endif %} -{% for key,header in spec.global.defaultHeaders %} + {%~ for key,header in spec.global.defaultHeaders %} "{{key}}": "{{header}}"{% if not loop.last %},{% endif %} -{% endfor %} + {%~ endfor %} ] open var config: [String: String] = [:] @@ -95,14 +95,14 @@ open class Client { } } -{% for header in spec.global.headers %} + {%~ for header in spec.global.headers %} /// /// Set {{header.key | caseUcfirst}} /// -{% if header.description %} + {%~ if header.description %} /// {{header.description}} /// -{% endif %} + {%~ endif %} /// @param String value /// /// @return Client @@ -113,7 +113,7 @@ open class Client { return self } -{% endfor %} + {%~ endfor %} /// /// Set self signed @@ -446,7 +446,12 @@ open class Client { || param is [Bool: Any] { encodedParams[key] = param } else { - encodedParams[key] = try! (param as! Encodable).toJson() + let value = try! (param as! Encodable).toJson() + + let range = value.index(value.startIndex, offsetBy: 1).. [String: Any] { return [ {%~ for property in definition.properties %} - "{{ property.name | escapeKeyword }}": {% if property.sub_schema %}{% if property.type == 'array' %}{{property.name | escapeKeyword | removeDollarSign}}.map { $0.toMap() }{% else %}{{property.name | escapeKeyword | removeDollarSign}}.toMap(){% endif %}{% else %}{{property.name | escapeKeyword | removeDollarSign}}{% endif %} as Any{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %} + "{{ property.name | escapeSwiftKeyword }}": {% if property.sub_schema %}{% if property.type == 'array' %}{{property.name | escapeSwiftKeyword | removeDollarSign}}.map { $0.toMap() }{% else %}{{property.name | escapeSwiftKeyword | removeDollarSign}}.toMap(){% endif %}{% else %}{{property.name | escapeSwiftKeyword | removeDollarSign}}{% endif %} as Any{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %} {%~ endfor %} {%~ if definition.additionalProperties %} @@ -50,7 +50,7 @@ public class {{ definition | modelType(spec) | raw }} { public static func from(map: [String: Any] ) -> {{ definition.name | caseUcfirst }} { return {{ definition.name | caseUcfirst }}( {%~ for property in definition.properties %} - {{ property.name | escapeKeyword | removeDollarSign }}: {% if property.sub_schema %}{% if property.type == 'array' %}(map["{{property.name }}"] as! [[String: Any]]).map { {{property.sub_schema | caseUcfirst}}.from(map: $0) }{% else %}{{property.sub_schema | caseUcfirst}}.from(map: map["{{property.name }}"] as! [String: Any]){% endif %}{% else %}map["{{property.name }}"] as{% if property.required %}!{% else %}?{% endif %} {{ property | propertyType(spec) | raw }}{% endif %}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %} + {{ property.name | escapeSwiftKeyword | removeDollarSign }}: {% if property.sub_schema %}{% if property.type == 'array' %}(map["{{property.name }}"] as! [[String: Any]]).map { {{property.sub_schema | caseUcfirst}}.from(map: $0) }{% else %}{{property.sub_schema | caseUcfirst}}.from(map: map["{{property.name }}"] as! [String: Any]){% endif %}{% else %}map["{{property.name }}"] as{% if property.required %}!{% else %}?{% endif %} {{ property | propertyType(spec) | raw }}{% endif %}{% if not loop.last or (loop.last and definition.additionalProperties) %},{% endif %} {%~ endfor %} {%~ if definition.additionalProperties %} diff --git a/templates/swift/Sources/Services/Service.swift.twig b/templates/swift/Sources/Services/Service.swift.twig index aad435162..2e0e7a2cc 100644 --- a/templates/swift/Sources/Services/Service.swift.twig +++ b/templates/swift/Sources/Services/Service.swift.twig @@ -2,10 +2,11 @@ import AsyncHTTPClient import Foundation import NIO import JSONCodable +import {{spec.title | caseUcfirst}}Enums import {{spec.title | caseUcfirst}}Models /// {{ service.description }} -open class {{ service.name | caseUcfirst }}: Service { +open class {{ service.name | caseUcfirst | overrideIdentifier }}: Service { {%~ for method in service.methods %} /// @@ -16,7 +17,7 @@ open class {{ service.name | caseUcfirst }}: Service { /// {%~ endif %} {%~ for parameter in method.parameters.all %} - /// @param {{ parameter | typeName | raw}} {{ parameter.name | caseCamel }} + /// @param {{ parameter | typeName(spec) | raw}} {{ parameter.name | caseCamel }} {%~ endfor %} /// @throws Exception /// @return array @@ -24,9 +25,9 @@ open class {{ service.name | caseUcfirst }}: Service { {%~ if method.type == "webAuth" %} @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {%~ endif %} - open func {{ method.name | caseCamel }}{% if method.responseModel | hasGenericType(spec) %}{% endif %}( + open func {{ method.name | caseCamel | overrideIdentifier }}{% if method.responseModel | hasGenericType(spec) %}{% endif %}( {%~ for parameter in method.parameters.all %} - {{ parameter.name | caseCamel | escapeKeyword }}: {{ parameter | typeName | raw }}{% if not parameter.required or parameter.nullable %}? = nil{% endif %}{% if not loop.last or 'multipart/form-data' in method.consumes or method.responseModel | hasGenericType(spec) %},{% endif %} + {{ parameter.name | caseCamel | escapeSwiftKeyword }}: {{ parameter | typeName(spec) | raw }}{% if not parameter.required or parameter.nullable %}? = nil{% endif %}{% if not loop.last or 'multipart/form-data' in method.consumes or method.responseModel | hasGenericType(spec) %},{% endif %} {%~ endfor %} {%~ if method.responseModel | hasGenericType(spec) %} @@ -82,7 +83,7 @@ open class {{ service.name | caseUcfirst }}: Service { /// {%~ endif %} {%~ for parameter in method.parameters.all %} - /// @param {{ parameter | typeName | raw}} {{ parameter.name | caseCamel }} + /// @param {{ parameter | typeName(spec) | raw}} {{ parameter.name | caseCamel }} {%~ endfor %} /// @throws Exception /// @return array @@ -92,7 +93,7 @@ open class {{ service.name | caseUcfirst }}: Service { {%~ endif %} open func {{ method.name | caseCamel }}( {%~ for parameter in method.parameters.all %} - {{ parameter.name | caseCamel | escapeKeyword }}: {{ parameter | typeName | raw }}{% if not parameter.required or parameter.nullable %}? = nil{% endif %}{% if not loop.last or 'multipart/form-data' in method.consumes %},{% endif %} + {{ parameter.name | caseCamel | escapeSwiftKeyword }}: {{ parameter | typeName(spec) | raw }}{% if not parameter.required or parameter.nullable %}? = nil{% endif %}{% if not loop.last or 'multipart/form-data' in method.consumes %},{% endif %} {%~ endfor %} {%~ if 'multipart/form-data' in method.consumes %} @@ -101,7 +102,7 @@ open class {{ service.name | caseUcfirst }}: Service { ) async throws -> {{ method | returnType(spec, '[String: AnyCodable]') | raw }} { return try await {{ method.name | caseCamel }}( {%~ for parameter in method.parameters.all %} - {{ parameter.name | caseCamel | escapeKeyword }}: {{ parameter.name | caseCamel | escapeKeyword }}, + {{ parameter.name | caseCamel | escapeSwiftKeyword }}: {{ parameter.name | caseCamel | escapeSwiftKeyword }}, {%~ endfor %} nestedType: [String: AnyCodable].self {%~ if 'multipart/form-data' in method.consumes %} diff --git a/templates/swift/base/params.twig b/templates/swift/base/params.twig index 518090ea8..1ca566d79 100644 --- a/templates/swift/base/params.twig +++ b/templates/swift/base/params.twig @@ -1,6 +1,6 @@ let apiPath: String = "{{ method.path }}" {%~ for parameter in method.parameters.path %} - .replacingOccurrences(of: "{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}", with: {{ parameter.name | caseCamel | escapeKeyword }}) + .replacingOccurrences(of: "{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}", with: {{ parameter.name | caseCamel | escapeSwiftKeyword }}{% if parameter.enumValues is not empty %}.rawValue{% endif %}) {%~ endfor %} {%~ if method.parameters.query | merge(method.parameters.body) | length <= 0 %} @@ -10,7 +10,7 @@ {%- else -%} let {%- endif %} apiParams: [String: Any?] = [ {%~ for parameter in method.parameters.query | merge(method.parameters.body) %} - "{{ parameter.name }}": {{ parameter.name | caseCamel | escapeKeyword }}{% if not loop.last or (method.type == 'location' or method.type == 'webAuth' and method.auth | length > 0) %},{% endif %} + "{{ parameter.name }}": {{ parameter.name | caseCamel | escapeSwiftKeyword }}{% if not loop.last or (method.type == 'location' or method.type == 'webAuth' and method.auth | length > 0) %},{% endif %} {%~ endfor %} {%~ if method.type == 'location' or method.type == 'webAuth' %} diff --git a/templates/swift/base/requests/api.twig b/templates/swift/base/requests/api.twig index e93264245..9c3a7b10f 100644 --- a/templates/swift/base/requests/api.twig +++ b/templates/swift/base/requests/api.twig @@ -4,5 +4,5 @@ headers: apiHeaders, params: apiParams{% if method.responseModel %}, converter: converter -{% endif %} + {%~ endif %} ) \ No newline at end of file diff --git a/templates/swift/docs/example.md.twig b/templates/swift/docs/example.md.twig index 2d4f478db..72125235d 100644 --- a/templates/swift/docs/example.md.twig +++ b/templates/swift/docs/example.md.twig @@ -1,4 +1,9 @@ import Appwrite +{% for parameter in method.parameters.all | filter((parameter) => parameter.required) %} +{% if parameter.enumValues | length > 0 %} +import AppwriteEnums +{% endif %} +{% endfor %} let client = Client() {% if method.auth|length > 0 %} @@ -12,10 +17,10 @@ let client = Client() let {{ service.name | caseCamel }} = {{ service.name | caseUcfirst }}(client{% if service.globalParams | length %}{% for parameter in service.globalParams %}, {{ parameter | paramExample }}{% endfor %}{% endif %}) -let {% if method.type == 'webAuth' %}success{% elseif method.type == 'location' %}byteBuffer{% elseif method.responseModel | length == 0 %}result{% else %}{{ method.responseModel | caseCamel | escapeKeyword }}{% endif %} = try await {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% if method.parameters.all | filter((param) => param.required) | length == 0 %}){{ '\n' }}{% endif %} +let {% if method.type == 'webAuth' %}success{% elseif method.type == 'location' %}bytes{% elseif method.responseModel | length == 0 %}result{% else %}{{ method.responseModel | caseCamel | escapeSwiftKeyword }}{% endif %} = try await {{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% if method.parameters.all | filter((param) => param.required) | length == 0 %}){{ '\n' }}{% endif %} {% for parameter in method.parameters.all | filter((parameter) => parameter.required) %} - {{parameter.name}}: {{ parameter | paramExample | escapeKeyword }}{% if not loop.last %},{% endif %} + {{ parameter.name }}: {% if parameter.enumValues | length > 0 %}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else %}{{ parameter | paramExample | escapeSwiftKeyword | raw }}{% endif %}{% if not loop.last %},{% endif %} {% if loop.last %} ) diff --git a/templates/web/docs/example.md.twig b/templates/web/docs/example.md.twig index 0d5862963..df2ef4b41 100644 --- a/templates/web/docs/example.md.twig +++ b/templates/web/docs/example.md.twig @@ -1,4 +1,4 @@ -import {{ '{' }} Client, {{service.name | caseUcfirst}} {{ '}' }} from "{{ language.params.npmPackage }}"; +import {{ '{' }} Client, {% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}{% endif %}{% if parameter.enumValues | length > 0%}{{parameter.enumName | caseUcfirst}},{% endif %}{% endif %}{% endfor %} {{service.name | caseUcfirst}} {{ '}' }} from "{{ language.params.npmPackage }}"; const client = new Client(); @@ -16,7 +16,7 @@ client {% endif %} {% if method.type == 'webAuth' %}// Go to OAuth provider login page {% endif %} -{% if method.type == 'webAuth' %}{% elseif method.type == 'location' %}const result = {% else %}const promise = {% endif %}{{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{{ parameter | paramExample }}{% endif %}{% endfor %}); +{% if method.type == 'webAuth' %}{% elseif method.type == 'location' %}const result = {% else %}const promise = {% endif %}{{ service.name | caseCamel }}.{{ method.name | caseCamel }}({% for parameter in method.parameters.all %}{% if parameter.required %}{% if not loop.first %}, {% endif %}{% if parameter.enumValues | length > 0 %}{{ parameter.enumName }}.{{ (parameter.enumKeys[0] ?? parameter.enumValues[0]) | caseEnumKey }}{% else%}{{ parameter | paramExample }}{% endif %}{% endif %}{% endfor %}); {% if method.type == 'webAuth' %}{% elseif method.type == 'location' %}console.log(result); // Resource URL{% else %}promise.then(function (response) { console.log(response); // Success diff --git a/templates/web/src/enums/enum.ts.twig b/templates/web/src/enums/enum.ts.twig new file mode 100644 index 000000000..bd20d2cb5 --- /dev/null +++ b/templates/web/src/enums/enum.ts.twig @@ -0,0 +1,6 @@ +export enum {{ enum.name | caseUcfirst }} { +{% for value in enum.enum %} +{% set key = enum.keys is empty ? value : enum.keys[loop.index0] %} + {{ key | caseUcfirst | replace({'-': ''})}} = '{{ value }}', +{% endfor %} +} \ No newline at end of file diff --git a/templates/web/src/index.ts.twig b/templates/web/src/index.ts.twig index 75ecd534d..a4b9fef71 100644 --- a/templates/web/src/index.ts.twig +++ b/templates/web/src/index.ts.twig @@ -6,4 +6,7 @@ export type { Models, Payload, RealtimeResponseEvent, UploadProgress } from './c export type { QueryTypes, QueryTypesList } from './query'; export { Permission } from './permission'; export { Role } from './role'; -export { ID } from './id'; \ No newline at end of file +export { ID } from './id'; +{% for enum in spec.enums %} +export { {{ enum | caseUcfirst }} } from './enums/{{enum | caseDash}}'; +{% endfor %} \ No newline at end of file diff --git a/templates/web/src/services/template.ts.twig b/templates/web/src/services/template.ts.twig index 585e5de60..70f4c4a53 100644 --- a/templates/web/src/services/template.ts.twig +++ b/templates/web/src/services/template.ts.twig @@ -2,6 +2,22 @@ import { Service } from '../service'; import { {{ spec.title | caseUcfirst}}Exception, Client } from '../client'; import type { Models } from '../models'; import type { UploadProgress, Payload } from '../client'; +{% set added = [] %} +{% for method in service.methods %} +{% for parameter in method.parameters.all %} +{% if parameter.enumValues is not empty %} +{% if parameter.enumName is not empty %} +{% set name = parameter.enumName %} +{% else %} +{% set name = parameter.name %} +{% endif %} +{% if name not in added %} +import { {{ name | caseUcfirst }} } from '../enums/{{ name | caseDash }}'; +{% set added = added|merge([name]) %} +{% endif %} +{% endif %} +{% endfor %} +{% endfor %} export class {{ service.name | caseUcfirst }} extends Service { diff --git a/tests/Android11Java11Test.php b/tests/Android11Java11Test.php index 9aa7a6c1a..0c38555b3 100644 --- a/tests/Android11Java11Test.php +++ b/tests/Android11Java11Test.php @@ -23,9 +23,8 @@ class Android11Java11Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, // ...Base::COOKIE_RESPONSES, diff --git a/tests/Android11Java8Test.php b/tests/Android11Java8Test.php index e79656ee8..1be68eea3 100644 --- a/tests/Android11Java8Test.php +++ b/tests/Android11Java8Test.php @@ -23,9 +23,8 @@ class Android11Java8Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, // ...Base::COOKIE_RESPONSES, diff --git a/tests/Android12Java11Test.php b/tests/Android12Java11Test.php index aead05eab..511d9d9bc 100644 --- a/tests/Android12Java11Test.php +++ b/tests/Android12Java11Test.php @@ -23,9 +23,8 @@ class Android12Java11Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, // ...Base::COOKIE_RESPONSES, diff --git a/tests/Android12Java8Test.php b/tests/Android12Java8Test.php index 1fe8f5340..999bf02b3 100644 --- a/tests/Android12Java8Test.php +++ b/tests/Android12Java8Test.php @@ -23,9 +23,8 @@ class Android12Java8Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, // ...Base::COOKIE_RESPONSES, diff --git a/tests/Android5Java11Test.php b/tests/Android5Java11Test.php index a0861181a..9eee0f823 100644 --- a/tests/Android5Java11Test.php +++ b/tests/Android5Java11Test.php @@ -23,9 +23,8 @@ class Android5Java11Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, // ...Base::COOKIE_RESPONSES, diff --git a/tests/Android5Java8Test.php b/tests/Android5Java8Test.php index 5d80aa266..3b14126ed 100644 --- a/tests/Android5Java8Test.php +++ b/tests/Android5Java8Test.php @@ -23,9 +23,8 @@ class Android5Java8Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, // ...Base::COOKIE_RESPONSES, diff --git a/tests/AppleSwift55Test.php b/tests/AppleSwift55Test.php index 4cbd655a0..875bb0c31 100644 --- a/tests/AppleSwift55Test.php +++ b/tests/AppleSwift55Test.php @@ -22,9 +22,8 @@ class AppleSwift55Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::REALTIME_RESPONSES, ...Base::COOKIE_RESPONSES, diff --git a/tests/Base.php b/tests/Base.php index 464291b45..47d549fd1 100644 --- a/tests/Base.php +++ b/tests/Base.php @@ -34,10 +34,9 @@ abstract class Base extends TestCase protected const GENERAL_RESPONSES = [ 'GET:/v1/mock/tests/general/redirect/done:passed', - 'POST:/v1/mock/tests/general/upload:passed', ]; - protected const EXTENDED_GENERAL_RESPONSES = [ + protected const DOWNLOAD_RESPONSES = [ 'GET:/v1/mock/tests/general/download:passed', ]; @@ -46,7 +45,14 @@ abstract class Base extends TestCase 'GET:/v1/mock/tests/general/get-cookie:passed', ]; - protected const LARGE_FILE_RESPONSES = [ + protected const ENUM_RESPONSES = [ + 'POST:/v1/mock/tests/general/enum:passed', + ]; + + protected const UPLOAD_RESPONSES = [ + 'POST:/v1/mock/tests/general/upload:passed', + 'POST:/v1/mock/tests/general/upload:passed', + 'POST:/v1/mock/tests/general/upload:passed', 'POST:/v1/mock/tests/general/upload:passed', ]; @@ -174,49 +180,30 @@ public function testHTTPSuccess(): void /** * Build SDK */ - foreach ($this->build as $key => $command) { - echo "Building phase #{$key} for {$this->language} package...\n"; - echo "Executing: {$command}\n"; - - $buildOutput = []; - - ob_end_clean(); + foreach ($this->build as $command) { echo "Build Executing: {$command}\n"; - ob_start(); - - exec($command, $buildOutput); - foreach ($buildOutput as $i => $row) { - echo "{$i}. {$row}\n"; - } + exec($command); } $output = []; - ob_end_clean(); echo "Env Executing: {$this->command}\n"; - ob_start(); exec($this->command, $output); - foreach ($output as $i => $row) { - echo "{$row}\n"; - } - $this->assertIsArray($output); do { - $removed = array_shift($output); + $removed = \array_shift($output); } while ($removed != 'Test Started' && sizeof($output) != 0); - $this->assertGreaterThanOrEqual(count($this->expectedOutput), count($output)); + echo \implode("\n", $output); - foreach ($this->expectedOutput as $i => $row) { - $this->assertEquals($output[$i], $row); - } + $this->assertEquals([], \array_diff($this->expectedOutput, $output)); } - private function rmdirRecursive($dir) + private function rmdirRecursive($dir): void { if (!\is_dir($dir)) { return; @@ -231,7 +218,7 @@ private function rmdirRecursive($dir) \unlink("$dir/$file"); } } - rmdir($dir); + \rmdir($dir); } public function getLanguage(): Language diff --git a/tests/CLINode14Test.php b/tests/CLINode14Test.php index 6b92eb423..2447746a5 100644 --- a/tests/CLINode14Test.php +++ b/tests/CLINode14Test.php @@ -25,7 +25,7 @@ class CLINode14Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - 'POST:/v1/mock/tests/general/upload:passed', //large file + ...Base::UPLOAD_RESPONSES, ]; public function getLanguage(): Language diff --git a/tests/CLINode16Test.php b/tests/CLINode16Test.php index 0dc378ca4..19e5e21bf 100644 --- a/tests/CLINode16Test.php +++ b/tests/CLINode16Test.php @@ -25,7 +25,7 @@ class CLINode16Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - 'POST:/v1/mock/tests/general/upload:passed', //large file + ...Base::UPLOAD_RESPONSES, ]; public function getLanguage(): Language diff --git a/tests/DartBetaTest.php b/tests/DartBetaTest.php index 85a8e8b9e..3f9f0b633 100644 --- a/tests/DartBetaTest.php +++ b/tests/DartBetaTest.php @@ -22,7 +22,8 @@ class DartBetaTest extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::QUERY_HELPER_RESPONSES, ...Base::PERMISSION_HELPER_RESPONSES, diff --git a/tests/DartStableTest.php b/tests/DartStableTest.php index ac21d95d5..29e0a7b97 100644 --- a/tests/DartStableTest.php +++ b/tests/DartStableTest.php @@ -22,7 +22,8 @@ class DartStableTest extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::QUERY_HELPER_RESPONSES, ...Base::PERMISSION_HELPER_RESPONSES, diff --git a/tests/Deno1193Test.php b/tests/Deno1193Test.php index a16066f85..cf5ac359f 100644 --- a/tests/Deno1193Test.php +++ b/tests/Deno1193Test.php @@ -19,7 +19,8 @@ class Deno1193Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::QUERY_HELPER_RESPONSES, ...Base::PERMISSION_HELPER_RESPONSES, diff --git a/tests/Deno1303Test.php b/tests/Deno1303Test.php index ef28031f7..0ad51abda 100644 --- a/tests/Deno1303Test.php +++ b/tests/Deno1303Test.php @@ -19,7 +19,8 @@ class Deno1303Test extends Base ...Base::FOO_RESPONSES, ...Base::BAR_RESPONSES, ...Base::GENERAL_RESPONSES, - ...Base::LARGE_FILE_RESPONSES, + ...Base::UPLOAD_RESPONSES, + ...Base::ENUM_RESPONSES, ...Base::EXCEPTION_RESPONSES, ...Base::QUERY_HELPER_RESPONSES, ...Base::PERMISSION_HELPER_RESPONSES, diff --git a/tests/DotNet31Test.php b/tests/DotNet31Test.php deleted file mode 100644 index 0852909fb..000000000 --- a/tests/DotNet31Test.php +++ /dev/null @@ -1,34 +0,0 @@ -() { "string in array" }, InputFile.FromStream(info.OpenRead(), "large_file.mp4", "video/mp4")); TestContext.WriteLine(mock.Result); + mock = await general.Enum(MockType.First); + TestContext.WriteLine(mock.Result); + try { await general.Error400(); diff --git a/tests/languages/flutter/tests.dart b/tests/languages/flutter/tests.dart index b6fb89e3b..4553cab3b 100644 --- a/tests/languages/flutter/tests.dart +++ b/tests/languages/flutter/tests.dart @@ -4,6 +4,8 @@ import 'package:path_provider_platform_interface/path_provider_platform_interfac import '../lib/packageName.dart'; import '../lib/client_io.dart'; import '../lib/models.dart'; +import '../lib/enums.dart'; +import '../lib/src/input_file.dart'; import 'dart:io'; class FakePathProvider extends PathProviderPlatform { @@ -17,7 +19,9 @@ class FakePathProvider extends PathProviderPlatform { void main() async { WidgetsFlutterBinding.ensureInitialized(); PathProviderPlatform.instance = FakePathProvider(); - Client client = Client(); + Client client = Client() + .addHeader("Origin", "http://localhost") + .setSelfSigned(); Foo foo = Foo(client); Bar bar = Bar(client); General general = General(client); @@ -28,7 +32,7 @@ void main() async { "wss://demo.appwrite.io/v1"); // change this later to appwrite.io Realtime realtime = Realtime(client); - // final rtsub = realtime.subscribe(["tests"]); + final rtsub = realtime.subscribe(["tests"]); await Future.delayed(Duration(seconds: 5)); client.addHeader('Origin', 'http://localhost'); @@ -79,13 +83,26 @@ void main() async { print(res['result']); var file = InputFile.fromPath(path: '../../resources/file.png', filename: 'file.png'); - response = await general.upload( - x: 'string', y: 123, z: ['string in array'], file: file); + response = await general.upload(x: 'string', y: 123, z: ['string in array'], file: file); print(response.result); file = InputFile.fromPath(path: '../../resources/large_file.mp4', filename: 'large_file.mp4'); - response = await general.upload( - x: 'string', y: 123, z: ['string in array'], file: file); + response = await general.upload(x: 'string', y: 123, z: ['string in array'], file: file); + print(response.result); + + var resource = File.fromUri(Uri.parse('../../resources/file.png')); + var bytes = await resource.readAsBytes(); + file = InputFile.fromBytes(bytes: bytes, filename: 'file.png'); + response = await general.upload(x: 'string', y: 123, z: ['string in array'], file: file); + print(response.result); + + resource = File.fromUri(Uri.parse('../../resources/large_file.mp4')); + bytes = await resource.readAsBytes(); + file = InputFile.fromBytes(bytes: bytes, filename: 'large_file.mp4'); + response = await general.upload(x: 'string', y: 123, z: ['string in array'], file: file); + print(response.result); + + response = await general.xenum(mockType: MockType.first); print(response.result); try { @@ -106,10 +123,10 @@ void main() async { print(e.message); } - // rtsub.stream.listen((message) { - // print(message.payload["response"]); - // rtsub.close(); - // }); + rtsub.stream.listen((message) { + print(message.payload["response"]); + rtsub.close(); + }); await Future.delayed(Duration(seconds: 5)); diff --git a/tests/languages/kotlin/Tests.kt b/tests/languages/kotlin/Tests.kt index 33b4ae06a..96e77b3b6 100644 --- a/tests/languages/kotlin/Tests.kt +++ b/tests/languages/kotlin/Tests.kt @@ -5,6 +5,7 @@ import io.appwrite.Permission import io.appwrite.Role import io.appwrite.ID import io.appwrite.Query +import io.appwrite.enums.MockType import io.appwrite.exceptions.AppwriteException import io.appwrite.extensions.fromJson import io.appwrite.extensions.toJson @@ -73,6 +74,9 @@ class ServiceTest { val result = general.redirect() writeToFile((result as Map)["result"] as String) + mock = general.enum(MockType.FIRST) + writeToFile(mock.result) + try { mock = general.upload("string", 123, listOf("string in array"), InputFile.fromPath("../../resources/file.png")) writeToFile(mock.result) @@ -100,6 +104,9 @@ class ServiceTest { writeToFile(ex.toString()) } + mock = general.enum(MockType.FIRST) + writeToFile(mock.result) + try { general.error400() } catch (e: AppwriteException) { diff --git a/tests/languages/node/test.js b/tests/languages/node/test.js index 259e7c0ea..70f94829a 100644 --- a/tests/languages/node/test.js +++ b/tests/languages/node/test.js @@ -1,7 +1,7 @@ const appwrite = require('../../sdks/node/index'); const InputFile = require('../../sdks/node/lib/inputFile'); -const fs = require('fs'); +const fs = require('fs').promises; async function start() { var response; @@ -10,9 +10,12 @@ async function start() { let Query = appwrite.Query; let Role = appwrite.Role; let ID = appwrite.ID; + let MockType = appwrite.MockType; // Init SDK - let client = new appwrite.Client(); + let client = new appwrite.Client() + .addHeader("Origin", "http://localhost") + .setSelfSigned(true); let foo = new appwrite.Foo(client); let bar = new appwrite.Bar(client); @@ -65,6 +68,17 @@ async function start() { response = await general.upload('string', 123, ['string in array'], InputFile.fromPath(__dirname + '/../../resources/large_file.mp4', 'large_file.mp4')); console.log(response.result); + let buffer= await fs.readFile('./tests/resources/file.png'); + response = await general.upload('string', 123, ['string in array'], appwrite.InputFile.fromBuffer(buffer, 'file.png')) + console.log(response.result); + + buffer = await fs.readFile('./tests/resources/large_file.mp4'); + response = await general.upload('string', 123, ['string in array'], appwrite.InputFile.fromBuffer(buffer, 'large_file.mp4')) + console.log(response.result); + + response = await general.enum(MockType.first); + console.log(response.result); + try { response = await general.error400(); } catch(error) { diff --git a/tests/languages/php/test.php b/tests/languages/php/test.php index 4f74f4e60..ed95ea92c 100644 --- a/tests/languages/php/test.php +++ b/tests/languages/php/test.php @@ -8,6 +8,7 @@ include __DIR__ . '/../../sdks/php/src/Appwrite/Role.php'; include __DIR__ . '/../../sdks/php/src/Appwrite/ID.php'; include __DIR__ . '/../../sdks/php/src/Appwrite/AppwriteException.php'; +include __DIR__ . '/../../sdks/php/src/Appwrite/Enums/MockType.php'; include __DIR__ . '/../../sdks/php/src/Appwrite/Services/Foo.php'; include __DIR__ . '/../../sdks/php/src/Appwrite/Services/Bar.php'; include __DIR__ . '/../../sdks/php/src/Appwrite/Services/General.php'; @@ -19,17 +20,19 @@ use Appwrite\Permission; use Appwrite\Role; use Appwrite\ID; +use Appwrite\Enums\MockType; use Appwrite\Services\Bar; use Appwrite\Services\Foo; use Appwrite\Services\General; -$client = new Client(); +$client = (new Client()) + ->addHeader("Origin", "http://localhost") + ->setSelfSigned(); + $foo = new Foo($client); $bar = new Bar($client); $general = new General($client); -$client->addHeader('Origin', 'http://localhost'); - echo "\nTest Started\n"; // Foo Service @@ -83,6 +86,9 @@ $response = $general->upload('string', 123, ['string in array'], InputFile::withPath(__DIR__ .'/../../resources/large_file.mp4')); echo "{$response['result']}\n"; +$response = $general->enum(MockType::FIRST()); +echo "{$response['result']}\n"; + try { $response = $general->error400(); } catch (AppwriteException $e) { diff --git a/tests/languages/python/tests.py b/tests/languages/python/tests.py index 99f70c301..f0be4c13d 100644 --- a/tests/languages/python/tests.py +++ b/tests/languages/python/tests.py @@ -8,10 +8,10 @@ from appwrite.permission import Permission from appwrite.role import Role from appwrite.id import ID +from appwrite.enums.mock_type import MockType import os.path - client = Client() foo = Foo(client) bar = Bar(client) @@ -75,6 +75,9 @@ response = general.upload('string', 123, ['string in array'], InputFile.from_bytes(data, 'large_file.mp4','video/mp4')) print(response['result']) +response = general.enum(MockType.FIRST) +print(response['result']) + try: response = general.error400() except AppwriteException as e: diff --git a/tests/languages/ruby/tests.rb b/tests/languages/ruby/tests.rb index 4a76966b0..ebccc8a7a 100644 --- a/tests/languages/ruby/tests.rb +++ b/tests/languages/ruby/tests.rb @@ -1,6 +1,7 @@ require_relative '../../sdks/ruby/lib/appwrite' include Appwrite +include Appwrite::Enums client = Client.new client.set_self_signed(true) @@ -82,6 +83,9 @@ puts e end +response = general.enum(mock_type: MockType::FIRST) +puts response.result + begin general.error400() rescue Exception => error diff --git a/tests/languages/swift/Tests.swift b/tests/languages/swift/Tests.swift index 948de3601..3662697a4 100644 --- a/tests/languages/swift/Tests.swift +++ b/tests/languages/swift/Tests.swift @@ -19,6 +19,7 @@ class Tests: XCTestCase { } func test() async throws { + do { let client = Client() .setProject("console") .addHeader(key: "Origin", value: "http://localhost") @@ -48,19 +49,19 @@ class Tests: XCTestCase { // Bar Tests - mock = try await bar.get(xrequired: "string", xdefault: 123, z: ["string in array"]) + mock = try await bar.get(required: "string", default: 123, z: ["string in array"]) print(mock.result) - mock = try await bar.post(xrequired: "string", xdefault: 123, z: ["string in array"]) + mock = try await bar.post(required: "string", default: 123, z: ["string in array"]) print(mock.result) - mock = try await bar.put(xrequired: "string", xdefault: 123, z: ["string in array"]) + mock = try await bar.put(required: "string", default: 123, z: ["string in array"]) print(mock.result) - mock = try await bar.patch(xrequired: "string", xdefault: 123, z: ["string in array"]) + mock = try await bar.patch(required: "string", default: 123, z: ["string in array"]) print(mock.result) - mock = try await bar.delete(xrequired: "string", xdefault: 123, z: ["string in array"]) + mock = try await bar.delete(required: "string", default: 123, z: ["string in array"]) print(mock.result) @@ -104,6 +105,9 @@ class Tests: XCTestCase { print(error.localizedDescription) } + mock = try await general.xenum(mockType: .first) + print(mock.result) + do { try await general.error400() } catch { @@ -164,5 +168,8 @@ class Tests: XCTestCase { mock = try await general.headers() print(mock.result) + } catch { + print(error.localizedDescription) + } } } diff --git a/tests/languages/web/index.html b/tests/languages/web/index.html index 17387180f..e8ef6bf85 100644 --- a/tests/languages/web/index.html +++ b/tests/languages/web/index.html @@ -20,8 +20,9 @@ let response; let responseRealtime = 'Realtime failed!'; // Init SDK - const { Client, Foo, Bar, General, Query, Permission, Role, ID } = Appwrite; + const { Client, Foo, Bar, General, Query, Permission, Role, ID, MockType } = Appwrite; const client = new Client(); + const foo = new Foo(client); const bar = new Bar(client); const general = new General(client); @@ -85,6 +86,12 @@ ); console.log(response.result); + console.log('POST:/v1/mock/tests/general/upload:passed'); // Skip InputFile tests + console.log('POST:/v1/mock/tests/general/upload:passed'); // Skip InputFile tests + + response = await general.enum(MockType.First); + console.log(response.result); + try { response = await general.empty(); } catch (error) { diff --git a/tests/languages/web/node.js b/tests/languages/web/node.js index 0ec235512..323ae2d11 100644 --- a/tests/languages/web/node.js +++ b/tests/languages/web/node.js @@ -1,4 +1,4 @@ -const { Client, Foo, Bar, General, Query, Permission, Role, ID } = require('./dist/cjs/sdk.js'); +const { Client, Foo, Bar, General, Query, Permission, Role, ID, MockType } = require('./dist/cjs/sdk.js'); async function start() { let response; @@ -46,6 +46,11 @@ async function start() { console.log('POST:/v1/mock/tests/general/upload:passed'); // Skip file upload test on Node.js console.log('POST:/v1/mock/tests/general/upload:passed'); // Skip big file upload test on Node.js + console.log('POST:/v1/mock/tests/general/upload:passed'); // Skip file upload test on Node.js + console.log('POST:/v1/mock/tests/general/upload:passed'); // Skip big file upload test on Node.js + + response = await general.enum(MockType.First); + console.log(response.result); try { response = await general.empty(); diff --git a/tests/resources/spec.json b/tests/resources/spec.json index 772602681..3b443e7c8 100644 --- a/tests/resources/spec.json +++ b/tests/resources/spec.json @@ -1,93 +1,131 @@ { "swagger": "2.0", "info": { - "version": "0.15.3", + "version": "1.4.2", "title": "Appwrite", - "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)", - "termsOfService": "https://appwrite.io/policy/terms", + "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)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", "contact": { "name": "Appwrite Team", - "url": "https://appwrite.io/support", + "url": "https:\/\/appwrite.io\/support", "email": "team@appwrite.io" }, "license": { "name": "BSD-3-Clause", - "url": "https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE" + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" } }, "host": "mockapi", "basePath": "/v1", "schemes": ["http"], - "consumes": ["application/json", "multipart/form-data"], - "produces": ["application/json"], + "consumes": [ + "application/json", + "multipart/form-data" + ], + "produces": [ + "application/json" + ], "securityDefinitions": { "Project": { "type": "apiKey", "name": "X-Appwrite-Project", "description": "Your project ID", "in": "header", - "x-appwrite": { "demo": "5df5acd0d48c2" } + "x-appwrite": { + "demo": "5df5acd0d48c2" + } }, "Key": { "type": "apiKey", "name": "X-Appwrite-Key", "description": "Your secret API key", "in": "header", - "x-appwrite": { "demo": "919c2d18fb5d4...a2ae413da83346ad2" } + "x-appwrite": { + "demo": "919c2d18fb5d4...a2ae413da83346ad2" + } }, "JWT": { "type": "apiKey", "name": "X-Appwrite-JWT", "description": "Your secret JSON Web Token", "in": "header", - "x-appwrite": { "demo": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..." } + "x-appwrite": { + "demo": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..." + } }, "Locale": { "type": "apiKey", "name": "X-Appwrite-Locale", "description": "", "in": "header", - "x-appwrite": { "demo": "en" } + "x-appwrite": { + "demo": "en" + } }, "Mode": { "type": "apiKey", "name": "X-Appwrite-Mode", "description": "", "in": "header", - "x-appwrite": { "demo": "" } + "x-appwrite": { + "demo": "" + } } }, "paths": { - "/mock/tests/bar": { + "\/mock\/tests\/bar": { "get": { "summary": "Get Bar", "operationId": "barGet", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["bar"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "bar" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "get", - "weight": 232, + "weight": 270, "cookies": false, "type": "", - "demo": "bar/get.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a get request.", + "demo": "bar\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a get request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "required", @@ -111,7 +149,9 @@ "required": true, "type": "array", "collectionFormat": "multi", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "in": "query" } ] @@ -119,32 +159,55 @@ "post": { "summary": "Post Bar", "operationId": "barPost", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["bar"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "bar" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "post", - "weight": 233, + "weight": 271, "cookies": false, "type": "", - "demo": "bar/post.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a post request.", + "demo": "bar\/post.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a post request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "\/mock\/tests\/bar", + "offline-key": "{required}", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -169,10 +232,16 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["required", "default", "z"] + "required": [ + "required", + "default", + "z" + ] } } ] @@ -180,32 +249,55 @@ "put": { "summary": "Put Bar", "operationId": "barPut", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["bar"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "bar" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "put", - "weight": 235, + "weight": 273, "cookies": false, "type": "", - "demo": "bar/put.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a put request.", + "demo": "bar\/put.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a put request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -230,10 +322,16 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["required", "default", "z"] + "required": [ + "required", + "default", + "z" + ] } } ] @@ -241,32 +339,55 @@ "patch": { "summary": "Patch Bar", "operationId": "barPatch", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["bar"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "bar" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "patch", - "weight": 234, + "weight": 272, "cookies": false, "type": "", - "demo": "bar/patch.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a patch request.", + "demo": "bar\/patch.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a patch request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -291,10 +412,16 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["required", "default", "z"] + "required": [ + "required", + "default", + "z" + ] } } ] @@ -302,32 +429,55 @@ "delete": { "summary": "Delete Bar", "operationId": "barDelete", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["bar"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "bar" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "delete", - "weight": 236, + "weight": 274, "cookies": false, "type": "", - "demo": "bar/delete.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a delete request.", + "demo": "bar\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a delete request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -352,45 +502,74 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["required", "default", "z"] + "required": [ + "required", + "default", + "z" + ] } } ] } }, - "/mock/tests/foo": { + "\/mock\/tests\/foo": { "get": { "summary": "Get Foo", "operationId": "fooGet", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["foo"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "foo" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "get", - "weight": 227, + "weight": 265, "cookies": false, "type": "", - "demo": "foo/get.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a get request.", + "demo": "foo\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a get request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "x", @@ -414,7 +593,9 @@ "required": true, "type": "array", "collectionFormat": "multi", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "in": "query" } ] @@ -422,32 +603,55 @@ "post": { "summary": "Post Foo", "operationId": "fooPost", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["foo"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "foo" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "post", - "weight": 228, + "weight": 266, "cookies": false, "type": "", - "demo": "foo/post.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a post request.", + "demo": "foo\/post.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a post request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -472,10 +676,16 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] } } ] @@ -483,32 +693,55 @@ "put": { "summary": "Put Foo", "operationId": "fooPut", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["foo"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "foo" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "put", - "weight": 230, + "weight": 268, "cookies": false, "type": "", - "demo": "foo/put.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a put request.", + "demo": "foo\/put.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a put request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -533,10 +766,16 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] } } ] @@ -544,32 +783,55 @@ "patch": { "summary": "Patch Foo", "operationId": "fooPatch", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["foo"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "foo" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "patch", - "weight": 229, + "weight": 267, "cookies": false, "type": "", - "demo": "foo/patch.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a patch request.", + "demo": "foo\/patch.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a patch request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -594,10 +856,16 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] } } ] @@ -605,32 +873,55 @@ "delete": { "summary": "Delete Foo", "operationId": "fooDelete", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["foo"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "foo" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "delete", - "weight": 231, + "weight": 269, "cookies": false, "type": "", - "demo": "foo/delete.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a delete request.", + "demo": "foo\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a delete request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "payload", @@ -655,352 +946,785 @@ "description": "Sample array param", "default": null, "x-example": null, - "items": { "type": "string" } + "items": { + "type": "string" + } } }, - "required": ["x", "y", "z"] + "required": [ + "x", + "y", + "z" + ] } } ] } }, - "/mock/tests/general/400-error": { + "\/mock\/tests\/general\/400-error": { "get": { "summary": "400 Error", "operationId": "generalError400", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], "description": "", "responses": { "400": { "description": "Error", - "schema": { "$ref": "#/definitions/error" } + "schema": { + "$ref": "#\/definitions\/error" + } } }, "x-appwrite": { "method": "error400", - "weight": 245, + "weight": 285, "cookies": false, "type": "", - "demo": "general/error400.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a 400 failed request.", + "demo": "general\/error400.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a 400 failed request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/500-error": { + "\/mock\/tests\/general\/500-error": { "get": { "summary": "500 Error", "operationId": "generalError500", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], "description": "", "responses": { "500": { "description": "Error", - "schema": { "$ref": "#/definitions/error" } + "schema": { + "$ref": "#\/definitions\/error" + } } }, "x-appwrite": { "method": "error500", - "weight": 246, + "weight": 286, "cookies": false, "type": "", - "demo": "general/error500.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a 500 failed request.", + "demo": "general\/error500.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a 500 failed request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/502-error": { + "\/mock\/tests\/general\/502-error": { "get": { "summary": "502 Error", "operationId": "generalError502", - "consumes": ["application/json"], - "produces": ["text/plain"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "text\/plain" + ], + "tags": [ + "general" + ], "description": "", "responses": { "502": { "description": "Any", - "schema": { "$ref": "#/definitions/any" } + "schema": { + "$ref": "#\/definitions\/any" + } } }, "x-appwrite": { "method": "error502", - "weight": 247, + "weight": 287, "cookies": false, "type": "", - "demo": "general/error502.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a 502 bad gateway.", + "demo": "general\/error502.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a 502 bad gateway.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client"], + "platforms": [ + "client" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [] }] + "security": [ + { + "Project": [] + } + ] } }, - "/mock/tests/general/download": { + "\/mock\/tests\/general\/download": { "get": { "summary": "Download File", "operationId": "generalDownload", - "consumes": ["application/json"], - "produces": ["*/*"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "*\/*" + ], + "tags": [ + "general" + ], "description": "", "responses": { - "200": { "description": "File", "schema": { "type": "file" } } + "200": { + "description": "File", + "schema": { + "type": "file" + } + } }, "x-appwrite": { "method": "download", - "weight": 237, + "weight": 276, "cookies": false, "type": "location", - "demo": "general/download.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a file download request.", + "demo": "general\/download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a file download request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/empty": { + "\/mock\/tests\/general\/empty": { "get": { "summary": "Empty Response", "operationId": "generalEmpty", - "consumes": ["application/json"], + "consumes": [ + "application\/json" + ], "produces": [], - "tags": ["general"], + "tags": [ + "general" + ], "description": "", - "responses": { "204": { "description": "No content" } }, + "responses": { + "204": { + "description": "No content" + } + }, "x-appwrite": { "method": "empty", - "weight": 243, + "weight": 282, "cookies": false, "type": "", - "demo": "general/empty.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock an empty response.", + "demo": "general\/empty.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock an empty response.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/get-cookie": { + "\/mock\/tests\/general\/enum": { + "post": { + "summary": "Enum Test", + "operationId": "generalEnum", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], + "description": "", + "responses": { + "200": { + "description": "Mock", + "schema": { + "$ref": "#\/definitions\/mock" + } + }, + "500": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "enum", + "weight": 284, + "cookies": false, + "type": "", + "demo": "general\/enum.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock an enum parameter.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "mockType": { + "type": "string", + "description": "Sample string param", + "default": null, + "x-example": "first", + "enum": [ + "first", + "second", + "third" + ], + "x-enum-name": null, + "x-enum-keys": [] + } + }, + "required": [ + "mockType" + ] + } + } + ] + } + }, + "\/mock\/tests\/general\/get-cookie": { "get": { "summary": "Get Cookie", "operationId": "generalGetCookie", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "getCookie", - "weight": 242, + "weight": 281, "cookies": false, "type": "", - "demo": "general/get-cookie.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a cookie response.", + "demo": "general\/get-cookie.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a cookie response.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/headers": { + "\/mock\/tests\/general\/headers": { "get": { "summary": "Get headers", "operationId": "generalHeaders", - "consumes": ["application/json"], + "consumes": [ + "application\/json" + ], "produces": [], - "tags": ["general"], + "tags": [ + "general" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "headers", - "weight": 244, + "weight": 275, "cookies": false, "type": "", - "demo": "general/headers.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterReturn headers from the request", + "demo": "general\/headers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterReturn headers from the request", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/redirect": { + "\/mock\/tests\/general\/nullable": { + "post": { + "summary": "Nullable Test", + "operationId": "generalNullable", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "general" + ], + "description": "", + "responses": { + "500": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "nullable", + "weight": 283, + "cookies": false, + "type": "", + "demo": "general\/nullable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a nullable parameter.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "string", + "description": "Sample string param", + "default": null, + "x-example": "[REQUIRED]" + }, + "nullable": { + "type": "string", + "description": "Sample string param", + "default": null, + "x-example": "[NULLABLE]", + "x-nullable": true + }, + "optional": { + "type": "string", + "description": "Sample string param", + "default": "", + "x-example": "[OPTIONAL]" + } + }, + "required": [ + "required", + "nullable" + ] + } + } + ] + } + }, + "\/mock\/tests\/general\/redirect": { "get": { "summary": "Redirect", "operationId": "generalRedirect", - "consumes": ["application/json"], - "produces": ["text/html"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "text\/html" + ], + "tags": [ + "general" + ], "description": "", - "responses": { "301": { "description": "No content" } }, + "responses": { + "301": { + "description": "No content" + } + }, "x-appwrite": { "method": "redirect", - "weight": 239, + "weight": 278, "cookies": false, "type": "", - "demo": "general/redirect.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a redirect request.", + "demo": "general\/redirect.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a redirect request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/redirect/done": { + "\/mock\/tests\/general\/redirect\/done": { "get": { "summary": "Redirected", "operationId": "generalRedirected", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "redirected", - "weight": 240, + "weight": 279, "cookies": false, "type": "", - "demo": "general/redirected.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a redirected request.", + "demo": "general\/redirected.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a redirected request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/set-cookie": { + "\/mock\/tests\/general\/set-cookie": { "get": { "summary": "Set Cookie", "operationId": "generalSetCookie", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["general"], + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "setCookie", - "weight": 241, + "weight": 280, "cookies": false, "type": "", - "demo": "general/set-cookie.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a set cookie request.", + "demo": "general\/set-cookie.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a set cookie request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }] + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] } }, - "/mock/tests/general/upload": { + "\/mock\/tests\/general\/upload": { "post": { "summary": "Upload File", "operationId": "generalUpload", - "consumes": ["multipart/form-data"], - "produces": ["application/json"], - "tags": ["general"], + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "general" + ], "description": "", "responses": { "200": { "description": "Mock", - "schema": { "$ref": "#/definitions/mock" } + "schema": { + "$ref": "#\/definitions\/mock" + } } }, "x-appwrite": { "method": "upload", - "weight": 238, + "weight": 277, "cookies": false, "type": "", - "demo": "general/upload.md", - "edit": "https://github.com/appwrite/appwrite/edit/masterMock a file upload request.", + "demo": "general\/upload.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterMock a file upload request.", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", "scope": "public", - "platforms": ["client", "server", "server"], + "platforms": [ + "client", + "server", + "server" + ], "packaging": false, - "auth": { "Project": [] } + "offline-model": "", + "offline-key": "", + "offline-response-key": "$id", + "auth": { + "Project": [] + } }, - "security": [{ "Project": [], "Key": [], "JWT": [] }], + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], "parameters": [ { "name": "x", @@ -1024,7 +1748,9 @@ "required": true, "type": "array", "collectionFormat": "multi", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "in": "formData" }, { @@ -1052,7 +1778,9 @@ { "name": "databases", "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", - "x-globalAttributes": ["databaseId"] + "x-globalAttributes": [ + "databaseId" + ] }, { "name": "locale", @@ -1069,6 +1797,11 @@ "description": "The Project service allows you to manage all the projects in your Appwrite server.", "x-globalAttributes": [] }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, { "name": "storage", "description": "The Storage service allows you to manage your project files.", @@ -1088,6 +1821,26 @@ "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] } ], "definitions": { @@ -1112,7 +1865,7 @@ }, "type": { "type": "string", - "description": "Error type. You can learn more about all the error types at https://appwrite.io/docs/error-codes#errorTypes", + "description": "Error type. You can learn more about all the error types at https:\/\/appwrite.io\/docs\/error-codes#errorTypes", "x-example": "not_found" }, "version": { @@ -1121,7 +1874,12 @@ "x-example": "1.0" } }, - "required": ["message", "code", "type", "version"] + "required": [ + "message", + "code", + "type", + "version" + ] }, "mock": { "description": "Mock", @@ -1133,11 +1891,13 @@ "x-example": "Success" } }, - "required": ["result"] + "required": [ + "result" + ] } }, "externalDocs": { "description": "Full API docs, specs and tutorials", - "url": "https://appwrite.io/docs" + "url": "https:\/\/appwrite.io\/docs" } } \ No newline at end of file