Merge pull request #3737 from appwrite/feat-additional-compression-support

Expose and introduce File Compression support
This commit is contained in:
Christy Jacob 2022-08-31 15:28:56 +02:00 committed by GitHub
commit 07b62cfbd3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 418 additions and 539 deletions

View file

@ -34,7 +34,8 @@ ENV PHP_REDIS_VERSION=5.3.7 \
PHP_SWOOLE_VERSION=v4.8.10 \
PHP_IMAGICK_VERSION=3.7.0 \
PHP_YAML_VERSION=2.2.2 \
PHP_MAXMINDDB_VERSION=v1.11.0
PHP_MAXMINDDB_VERSION=v1.11.0 \
PHP_ZSTD_VERSION="4504e4186e79b197cfcb75d4d09aa47ef7d92fe9 "
RUN \
apk add --no-cache --virtual .deps \
@ -50,7 +51,8 @@ RUN \
yaml-dev \
imagemagick \
imagemagick-dev \
libmaxminddb-dev
libmaxminddb-dev \
zstd-dev
RUN docker-php-ext-install sockets
@ -123,6 +125,16 @@ RUN \
./configure && \
make && make install
# Zstd Compression
FROM compile as zstd
RUN git clone --recursive -n https://github.com/kjdev/php-ext-zstd.git \
&& cd php-ext-zstd \
&& git checkout $PHP_ZSTD_VERSION \
&& phpize \
&& ./configure --with-libzstd \
&& make && make install
# Rust Extensions Compile Image
FROM php:8.0.18-cli as rust_compile
@ -293,6 +305,7 @@ COPY --from=yaml /usr/local/lib/php/extensions/no-debug-non-zts-20200930/yaml.so
COPY --from=maxmind /usr/local/lib/php/extensions/no-debug-non-zts-20200930/maxminddb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
COPY --from=mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20200930/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
COPY --from=scrypt /usr/local/lib/php/extensions/php-scrypt/target/libphp_scrypt.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
COPY --from=zstd /usr/local/lib/php/extensions/no-debug-non-zts-20200930/zstd.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/
# Add Source Code
COPY ./app /usr/src/code/app
@ -350,6 +363,7 @@ RUN echo extension=imagick.so >> /usr/local/etc/php/conf.d/imagick.ini
RUN echo extension=yaml.so >> /usr/local/etc/php/conf.d/yaml.ini
RUN echo extension=maxminddb.so >> /usr/local/etc/php/conf.d/maxminddb.ini
RUN echo extension=libphp_scrypt.so >> /usr/local/etc/php/conf.d/libphp_scrypt.ini
RUN echo extension=zstd.so >> /usr/local/etc/php/conf.d/zstd.ini
RUN if [ "$DEBUG" == "true" ]; then printf "zend_extension=yasd \nyasd.debug_mode=remote \nyasd.init_file=/usr/local/dev/yasd_init.php \nyasd.remote_port=9005 \nyasd.log_level=-1" >> /usr/local/etc/php/conf.d/yasd.ini; fi
RUN if [ "$DEBUG" == "true" ]; then echo "opcache.enable=0" >> /usr/local/etc/php/conf.d/appwrite.ini; fi

View file

@ -2875,6 +2875,16 @@ $collections = [
'required' => true,
'array' => true,
],
[
'$id' => 'compression',
'type' => Database::VAR_STRING,
'signed' => true,
'size' => 10,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => ID::custom('encryption'),
'type' => Database::VAR_BOOLEAN,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,6 @@ use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Usage\Stats;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Config\Config;
@ -29,8 +28,8 @@ use Appwrite\Utopia\Database\Validator\Queries\Buckets;
use Appwrite\Utopia\Database\Validator\Queries\Files;
use Utopia\Image\Image;
use Utopia\Storage\Compression\Algorithms\GZIP;
use Utopia\Storage\Compression\Algorithms\Zstd;
use Utopia\Storage\Device;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Storage;
use Utopia\Storage\Validator\File;
use Utopia\Storage\Validator\FileExt;
@ -39,7 +38,6 @@ use Utopia\Storage\Validator\Upload;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Boolean;
use Utopia\Validator\HexColor;
use Utopia\Validator\Integer;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
@ -66,12 +64,13 @@ App::post('/v1/storage/buckets')
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
->param('maximumFileSize', (int) App::getEnv('_APP_STORAGE_LIMIT', 0), new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self-hosted setups you can change the max limit by changing the `_APP_STORAGE_LIMIT` environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
->param('compression', 'none', new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
$bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId;
@ -120,6 +119,7 @@ App::post('/v1/storage/buckets')
'allowedFileExtensions' => $allowedFileExtensions,
'fileSecurity' => $fileSecurity,
'enabled' => $enabled,
'compression' => $compression,
'encryption' => $encryption,
'antivirus' => $antivirus,
'search' => implode(' ', [$bucketId, $name]),
@ -234,12 +234,13 @@ App::put('/v1/storage/buckets/:bucketId')
->param('enabled', true, new Boolean(true), 'Is bucket enabled?', true)
->param('maximumFileSize', null, new Range(1, (int) App::getEnv('_APP_STORAGE_LIMIT', 0)), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human((int)App::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)', true)
->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true)
->param('compression', 'none', new WhiteList([COMPRESSION_TYPE_NONE, COMPRESSION_TYPE_GZIP, COMPRESSION_TYPE_ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true)
->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true)
->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true)
->inject('response')
->inject('dbForProject')
->inject('events')
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $events) {
$bucket = $dbForProject->getDocument('buckets', $bucketId);
if ($bucket->isEmpty()) {
@ -268,6 +269,7 @@ App::put('/v1/storage/buckets/:bucketId')
->setAttribute('fileSecurity', $fileSecurity)
->setAttribute('enabled', $enabled)
->setAttribute('encryption', $encryption)
->setAttribute('compression', $compression)
->setAttribute('antivirus', $antivirus));
$events
@ -502,9 +504,18 @@ App::post('/v1/storage/buckets/:bucketId/files')
$mimeType = $deviceFiles->getFileMimeType($path); // Get mime-type before compression and encryption
$data = '';
// Compression
if ($fileSize <= APP_STORAGE_READ_BUFFER) {
$algorithm = $bucket->getAttribute('compression', 'none');
if ($fileSize <= APP_STORAGE_READ_BUFFER && $algorithm != 'none') {
$data = $deviceFiles->read($path);
$compressor = new GZIP();
switch ($algorithm) {
case 'zstd':
$compressor = new Zstd();
break;
case 'gzip':
default:
$compressor = new GZIP();
break;
}
$data = $compressor->compress($data);
}
@ -524,8 +535,6 @@ App::post('/v1/storage/buckets/:bucketId/files')
}
$sizeActual = $deviceFiles->getFileSize($path);
$algorithm = empty($compressor) ? '' : $compressor->getName();
$fileHash = $deviceFiles->getFileHash($path);
if ($bucket->getAttribute('encryption', true) && $fileSize <= APP_STORAGE_READ_BUFFER) {
@ -840,7 +849,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
$path = $file->getAttribute('path');
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
$algorithm = $file->getAttribute('algorithm');
$algorithm = $file->getAttribute('algorithm', 'none');
$cipher = $file->getAttribute('openSSLCipher');
$mime = $file->getAttribute('mimeType');
if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) App::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) {
@ -851,16 +860,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
$path = $fileLogos['default_image'];
}
$algorithm = null;
$algorithm = 'none';
$cipher = null;
$background = (empty($background)) ? 'eceff1' : $background;
$type = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
$deviceFiles = $deviceLocal;
}
$compressor = new GZIP();
if (!$deviceFiles->exists($path)) {
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
}
@ -885,8 +891,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
);
}
if (!empty($algorithm)) {
$source = $compressor->decompress($source);
switch ($algorithm) {
case 'zstd':
$compressor = new Zstd();
$source = $compressor->decompress($source);
break;
case 'gzip':
$compressor = new GZIP();
$source = $compressor->decompress($source);
break;
}
$image = new Image($source);
@ -1021,12 +1034,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
);
}
if (!empty($file->getAttribute('algorithm', ''))) {
if (empty($source)) {
$source = $deviceFiles->read($path);
}
$compressor = new GZIP();
$source = $compressor->decompress($source);
switch ($file->getAttribute('algorithm', 'none')) {
case 'zstd':
if (empty($source)) {
$source = $deviceFiles->read($path);
}
$compressor = new Zstd();
$source = $compressor->decompress($source);
break;
case 'gzip':
if (empty($source)) {
$source = $deviceFiles->read($path);
}
$compressor = new GZIP();
$source = $compressor->decompress($source);
break;
}
if (!empty($source)) {
@ -1162,12 +1184,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
);
}
if (!empty($file->getAttribute('algorithm', ''))) {
if (empty($source)) {
$source = $deviceFiles->read($path);
}
$compressor = new GZIP();
$source = $compressor->decompress($source);
switch ($file->getAttribute('algorithm', 'none')) {
case 'zstd':
if (empty($source)) {
$source = $deviceFiles->read($path);
}
$compressor = new Zstd();
$source = $compressor->decompress($source);
break;
case 'gzip':
if (empty($source)) {
$source = $deviceFiles->read($path);
}
$compressor = new GZIP();
$source = $compressor->decompress($source);
break;
}
if (!empty($source)) {

View file

@ -169,6 +169,7 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
'maximumFileSize' => (int) App::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB
'allowedFileExtensions' => [],
'enabled' => true,
'compression' => 'gzip',
'encryption' => true,
'antivirus' => true,
'fileSecurity' => true,

View file

@ -151,6 +151,10 @@ const DELETE_TYPE_BUCKETS = 'buckets';
const DELETE_TYPE_SESSIONS = 'sessions';
const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp';
const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource';
// Compression type
const COMPRESSION_TYPE_NONE = 'none';
const COMPRESSION_TYPE_GZIP = 'gzip';
const COMPRESSION_TYPE_ZSTD = 'zstd';
// Mail Types
const MAIL_TYPE_VERIFICATION = 'verification';
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';

View file

@ -416,6 +416,13 @@ $fileUpdatePermissions = $this->getParam('fileUpdatePermissions', null);
<label for="bucket-maximum-file-size">Maximum File Size (bytes) <span class="tooltip small" data-tooltip="Limit file size allowed in the bucket."><i class="icon-info-circled"></i></span></label>
<input name="maximumFileSize" id="bucket-maximum-file-size" type="number" autocomplete="off" data-ls-bind="{{project-bucket.maximumFileSize}}" min="1" data-cast-to="integer" />
<label for="compression">Compression</label>
<select id="compression" data-ls-bind="{{project-bucket.compression}}" name="compression">
<option value="none">None</option>
<option value="gzip">Gzip</option>
<option value="zstd">Zstd</option>
</select>
<div class="margin-bottom">
<input name="enabled" type="hidden" data-forms-switch data-cast-to="boolean" data-ls-bind="{{project-bucket.enabled}}" /> &nbsp; Enabled <span class="tooltip" data-tooltip="Mark whether bucket is enabled"><i class="icon-info-circled"></i></span>
</div>

View file

@ -57,7 +57,7 @@
"utopia-php/preloader": "0.2.*",
"utopia-php/domains": "1.1.*",
"utopia-php/swoole": "0.3.*",
"utopia-php/storage": "0.9.*",
"utopia-php/storage": "0.11.*",
"utopia-php/websocket": "0.1.0",
"utopia-php/image": "0.5.*",
"utopia-php/orchestration": "0.6.*",

27
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "039de21eff3a27955696a9f6f645c548",
"content-hash": "7c41d4bcb13c34e72039e3de7e84f732",
"packages": [
{
"name": "adhocore/jwt",
@ -2556,19 +2556,22 @@
},
{
"name": "utopia-php/storage",
"version": "0.9.0",
"version": "0.11.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "c7912481a56e17cc86358fa8de57309de5e88ef7"
"reference": "59802cf281d1976560cf6e353f250a9b870efddc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/c7912481a56e17cc86358fa8de57309de5e88ef7",
"reference": "c7912481a56e17cc86358fa8de57309de5e88ef7",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/59802cf281d1976560cf6e353f250a9b870efddc",
"reference": "59802cf281d1976560cf6e353f250a9b870efddc",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"ext-zlib": "*",
"ext-zstd": "*",
"php": ">=8.0",
"utopia-php/framework": "0.*.*"
},
@ -2602,9 +2605,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/0.9.0"
"source": "https://github.com/utopia-php/storage/tree/0.11.0"
},
"time": "2022-05-19T11:05:45+00:00"
"time": "2022-08-31T09:17:31+00:00"
},
{
"name": "utopia-php/swoole",
@ -2841,12 +2844,12 @@
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "6e630a62f522ac68a7056bebf81cd032c7a053ba"
"reference": "532d4d15ec8f11539972f2848c2e230c49b24f65"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6e630a62f522ac68a7056bebf81cd032c7a053ba",
"reference": "6e630a62f522ac68a7056bebf81cd032c7a053ba",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/532d4d15ec8f11539972f2848c2e230c49b24f65",
"reference": "532d4d15ec8f11539972f2848c2e230c49b24f65",
"shasum": ""
},
"require": {
@ -2883,7 +2886,7 @@
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/feat-new-headers"
},
"time": "2022-08-29T10:43:33+00:00"
"time": "2022-08-20T07:42:55+00:00"
},
{
"name": "doctrine/instantiator",
@ -5383,5 +5386,5 @@
"platform-overrides": {
"php": "8.0"
},
"plugin-api-version": "2.2.0"
"plugin-api-version": "2.3.0"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -522,7 +522,7 @@ return new Promise(function(resolve,reject){let request=new XMLHttpRequest(),key
request.onload=function(){if(4===request.readyState&&399>=request.status){let data=request.response;let contentType=this.getResponseHeader('content-type');contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;}
resolve(data);}else{reject(new Error(request.statusText));}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);}
request.onerror=function(){reject(new Error("Network Error"));};request.send(params);})};return{'get':function(path,headers={},params={}){return call('GET',path+((params.length>0)?'?'+buildQuery(params):''),headers,{});},'post':function(path,headers={},params={},progress=null){return call('POST',path,headers,params,progress);},'put':function(path,headers={},params={},progress=null){return call('PUT',headers,params,progress);},'patch':function(path,headers={},params={},progress=null){return call('PATCH',path,headers,params,progress);},'delete':function(path,headers={},params={},progress=null){return call('DELETE',path,headers,params,progress);},'addGlobalParam':addGlobalParam,'addGlobalHeader':addGlobalHeader}}(window.document);let analytics={create:function(id,source,activity,url){return http.post('/analytics',{'content-type':'application/json'},{id:id,source:source,activity:activity,url:url,version:env.VERSION,setup:env.SETUP});},};return{analytics:analytics,};},true);})(window);(function(window){"use strict";window.ls.container.set('console',function(window){var client=new Appwrite.Client();var endpoint=window.location.origin+'/v1';client.setEndpoint(endpoint).setProject('console').setLocale(APP_ENV.LOCALE);return{client:client,account:new Appwrite.Account(client),avatars:new Appwrite.Avatars(client),databases:new Appwrite.Databases(client),functions:new Appwrite.Functions(client),health:new Appwrite.Health(client),locale:new Appwrite.Locale(client),projects:new Appwrite.Projects(client),storage:new Appwrite.Storage(client),teams:new Appwrite.Teams(client),users:new Appwrite.Users(client)}},true);})(window);(function(window){"use strict";window.ls.container.set('date',function(){function format(format,datetime){if(!datetime){return null;}
return new Intl.DateTimeFormat('en-US',{timeZone:'UTC',hourCycle:'h24',...format}).format(new Date(datetime));}
return new Intl.DateTimeFormat(navigator.languages,{hourCycle:'h24',...format}).format(new Date(datetime));}
return{format:format,}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,from,to,){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,from,to));return value;}
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'float':value=parseFloat(value);break;case'string':value=value.toString();if(value.length===0){value=null;}
break;case'json':value=(value)?JSON.parse(value):[];break;case'array':if(value&&value.constructor&&value.constructor===Array){break;}

View file

@ -1,29 +1,29 @@
(function (exports, isomorphicFormData, crossFetch) {
'use strict';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
class Service {
@ -93,7 +93,10 @@
mode: '',
};
this.headers = {
'x-sdk-version': 'appwrite:web:6.0.0',
'x-sdk-name': 'Console',
'x-sdk-platform': 'console',
'x-sdk-language': 'web',
'x-sdk-version': '6.0.0',
'X-Appwrite-Response-Format': '0.15.0',
};
this.realtime = {
@ -563,20 +566,16 @@
* Get currently logged in user list of latest security activity logs. Each
* log returns user IP address, location and date and time of log.
*
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @throws {AppwriteException}
* @returns {Promise}
*/
getLogs(limit, offset) {
getLogs(queries) {
return __awaiter(this, void 0, void 0, function* () {
let path = '/account/logs';
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
@ -1649,37 +1648,21 @@
* Get a list of all databases from the current Appwrite project. You can use
* the search parameter to filter your results.
*
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
list(search, limit, offset, cursor, cursorDirection, orderType) {
list(queries, search) {
return __awaiter(this, void 0, void 0, function* () {
let path = '/databases';
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -1822,40 +1805,24 @@
* can use the search parameter to filter your results.
*
* @param {string} databaseId
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
listCollections(databaseId, search, limit, offset, cursor, cursorDirection, orderType) {
listCollections(databaseId, queries, search) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof databaseId === 'undefined') {
throw new AppwriteException('Missing required parameter: "databaseId"');
}
let path = '/databases/{databaseId}/collections'.replace('{databaseId}', databaseId);
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -2580,16 +2547,10 @@
* @param {string} databaseId
* @param {string} collectionId
* @param {string[]} queries
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string[]} orderAttributes
* @param {string[]} orderTypes
* @throws {AppwriteException}
* @returns {Promise}
*/
listDocuments(databaseId, collectionId, queries, limit, offset, cursor, cursorDirection, orderAttributes, orderTypes) {
listDocuments(databaseId, collectionId, queries) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof databaseId === 'undefined') {
throw new AppwriteException('Missing required parameter: "databaseId"');
@ -2602,24 +2563,6 @@
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderAttributes !== 'undefined') {
payload['orderAttributes'] = orderAttributes;
}
if (typeof orderTypes !== 'undefined') {
payload['orderTypes'] = orderTypes;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -2781,12 +2724,11 @@
* @param {string} databaseId
* @param {string} collectionId
* @param {string} documentId
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @throws {AppwriteException}
* @returns {Promise}
*/
listDocumentLogs(databaseId, collectionId, documentId, limit, offset) {
listDocumentLogs(databaseId, collectionId, documentId, queries) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof databaseId === 'undefined') {
throw new AppwriteException('Missing required parameter: "databaseId"');
@ -2799,11 +2741,8 @@
}
let path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/logs'.replace('{databaseId}', databaseId).replace('{collectionId}', collectionId).replace('{documentId}', documentId);
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
@ -2951,12 +2890,11 @@
*
* @param {string} databaseId
* @param {string} collectionId
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @throws {AppwriteException}
* @returns {Promise}
*/
listCollectionLogs(databaseId, collectionId, limit, offset) {
listCollectionLogs(databaseId, collectionId, queries) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof databaseId === 'undefined') {
throw new AppwriteException('Missing required parameter: "databaseId"');
@ -2966,11 +2904,8 @@
}
let path = '/databases/{databaseId}/collections/{collectionId}/logs'.replace('{databaseId}', databaseId).replace('{collectionId}', collectionId);
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
@ -3008,28 +2943,24 @@
});
}
/**
* List Collection Logs
* List Database Logs
*
* Get the collection activity logs list by its unique ID.
* Get the database activity logs list by its unique ID.
*
* @param {string} databaseId
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @throws {AppwriteException}
* @returns {Promise}
*/
listLogs(databaseId, limit, offset) {
listLogs(databaseId, queries) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof databaseId === 'undefined') {
throw new AppwriteException('Missing required parameter: "databaseId"');
}
let path = '/databases/{databaseId}/logs'.replace('{databaseId}', databaseId);
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
@ -3074,37 +3005,21 @@
* Get a list of all the project's functions. You can use the query params to
* filter your results.
*
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
list(search, limit, offset, cursor, cursorDirection, orderType) {
list(queries, search) {
return __awaiter(this, void 0, void 0, function* () {
let path = '/functions';
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -3309,40 +3224,24 @@
* params to filter your results.
*
* @param {string} functionId
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
listDeployments(functionId, search, limit, offset, cursor, cursorDirection, orderType) {
listDeployments(functionId, queries, search) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof functionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "functionId"');
}
let path = '/functions/{functionId}/deployments'.replace('{functionId}', functionId);
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -3556,36 +3455,24 @@
* different API modes](/docs/admin).
*
* @param {string} functionId
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @param {string} search
* @param {string} cursor
* @param {string} cursorDirection
* @throws {AppwriteException}
* @returns {Promise}
*/
listExecutions(functionId, limit, offset, search, cursor, cursorDirection) {
listExecutions(functionId, queries, search) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof functionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "functionId"');
}
let path = '/functions/{functionId}/executions'.replace('{functionId}', functionId);
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -5217,37 +5104,21 @@
* Get a list of all the storage buckets. You can use the query params to
* filter your results.
*
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
listBuckets(search, limit, offset, cursor, cursorDirection, orderType) {
listBuckets(queries, search) {
return __awaiter(this, void 0, void 0, function* () {
let path = '/storage/buckets';
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -5266,12 +5137,13 @@
* @param {boolean} enabled
* @param {number} maximumFileSize
* @param {string[]} allowedFileExtensions
* @param {string} compression
* @param {boolean} encryption
* @param {boolean} antivirus
* @throws {AppwriteException}
* @returns {Promise}
*/
createBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, encryption, antivirus) {
createBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, compression, encryption, antivirus) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof bucketId === 'undefined') {
throw new AppwriteException('Missing required parameter: "bucketId"');
@ -5305,6 +5177,9 @@
if (typeof allowedFileExtensions !== 'undefined') {
payload['allowedFileExtensions'] = allowedFileExtensions;
}
if (typeof compression !== 'undefined') {
payload['compression'] = compression;
}
if (typeof encryption !== 'undefined') {
payload['encryption'] = encryption;
}
@ -5352,12 +5227,13 @@
* @param {boolean} enabled
* @param {number} maximumFileSize
* @param {string[]} allowedFileExtensions
* @param {string} compression
* @param {boolean} encryption
* @param {boolean} antivirus
* @throws {AppwriteException}
* @returns {Promise}
*/
updateBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, encryption, antivirus) {
updateBucket(bucketId, name, fileSecurity, permissions, enabled, maximumFileSize, allowedFileExtensions, compression, encryption, antivirus) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof bucketId === 'undefined') {
throw new AppwriteException('Missing required parameter: "bucketId"');
@ -5388,6 +5264,9 @@
if (typeof allowedFileExtensions !== 'undefined') {
payload['allowedFileExtensions'] = allowedFileExtensions;
}
if (typeof compression !== 'undefined') {
payload['compression'] = compression;
}
if (typeof encryption !== 'undefined') {
payload['encryption'] = encryption;
}
@ -5430,40 +5309,24 @@
* project's files. [Learn more about different API modes](/docs/admin).
*
* @param {string} bucketId
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
listFiles(bucketId, search, limit, offset, cursor, cursorDirection, orderType) {
listFiles(bucketId, queries, search) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof bucketId === 'undefined') {
throw new AppwriteException('Missing required parameter: "bucketId"');
}
let path = '/storage/buckets/{bucketId}/files'.replace('{bucketId}', bucketId);
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -5848,37 +5711,21 @@
* In admin mode, this endpoint returns a list of all the teams in the current
* project. [Learn more about different API modes](/docs/admin).
*
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
list(search, limit, offset, cursor, cursorDirection, orderType) {
list(queries, search) {
return __awaiter(this, void 0, void 0, function* () {
let path = '/teams';
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -6004,23 +5851,19 @@
* Get the team activity logs list by its unique ID.
*
* @param {string} teamId
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @throws {AppwriteException}
* @returns {Promise}
*/
listLogs(teamId, limit, offset) {
listLogs(teamId, queries) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof teamId === 'undefined') {
throw new AppwriteException('Missing required parameter: "teamId"');
}
let path = '/teams/{teamId}/logs'.replace('{teamId}', teamId);
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
@ -6035,40 +5878,24 @@
* members have read access to this endpoint.
*
* @param {string} teamId
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
getMemberships(teamId, search, limit, offset, cursor, cursorDirection, orderType) {
getMemberships(teamId, queries, search) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof teamId === 'undefined') {
throw new AppwriteException('Missing required parameter: "teamId"');
}
let path = '/teams/{teamId}/memberships'.replace('{teamId}', teamId);
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -6284,37 +6111,21 @@
* Get a list of all the project's users. You can use the query params to
* filter your results.
*
* @param {string} queries
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} cursor
* @param {string} cursorDirection
* @param {string} orderType
* @throws {AppwriteException}
* @returns {Promise}
*/
list(search, limit, offset, cursor, cursorDirection, orderType) {
list(queries, search) {
return __awaiter(this, void 0, void 0, function* () {
let path = '/users';
let payload = {};
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
if (typeof search !== 'undefined') {
payload['search'] = search;
}
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
}
if (typeof cursor !== 'undefined') {
payload['cursor'] = cursor;
}
if (typeof cursorDirection !== 'undefined') {
payload['cursorDirection'] = cursorDirection;
}
if (typeof orderType !== 'undefined') {
payload['orderType'] = orderType;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {
'content-type': 'application/json',
@ -6852,23 +6663,19 @@
* Get the user activity logs list by its unique ID.
*
* @param {string} userId
* @param {number} limit
* @param {number} offset
* @param {string} queries
* @throws {AppwriteException}
* @returns {Promise}
*/
getLogs(userId, limit, offset) {
getLogs(userId, queries) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof userId === 'undefined') {
throw new AppwriteException('Missing required parameter: "userId"');
}
let path = '/users/{userId}/logs'.replace('{userId}', userId);
let payload = {};
if (typeof limit !== 'undefined') {
payload['limit'] = limit;
}
if (typeof offset !== 'undefined') {
payload['offset'] = offset;
if (typeof queries !== 'undefined') {
payload['queries'] = queries;
}
const uri = new URL(this.client.config.endpoint + path);
return yield this.client.call('get', uri, {

View file

@ -66,6 +66,13 @@ class Bucket extends Model
'example' => ['jpg', 'png'],
'array' => true
])
->addRule('compression', [
'type' => self::TYPE_STRING,
'description' => 'Compression algorithm choosen for compression. Will be one of ' . COMPRESSION_TYPE_NONE . ', [' . COMPRESSION_TYPE_GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . COMPRESSION_TYPE_ZSTD . '](https://en.wikipedia.org/wiki/Zstd).',
'default' => [],
'example' => 'gzip',
'array' => false
])
->addRule('encryption', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Bucket is encrypted.',

View file

@ -243,6 +243,55 @@ trait StorageBase
return ['bucketId' => $bucketId, 'fileId' => $file['body']['$id'], 'largeFileId' => $largeFile['body']['$id'], 'largeBucketId' => $bucket2['body']['$id']];
}
public function testCreateBucketFileZstdCompression(): array
{
$bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'bucketId' => ID::unique(),
'name' => 'Test Bucket',
'fileSecurity' => true,
'maximumFileSize' => 2000000, //2MB
'allowedFileExtensions' => ["jpg", "png"],
'compression' => 'zstd',
'permissions' => [
Permission::read(Role::any()),
Permission::create(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]);
$this->assertEquals(201, $bucket['headers']['status-code']);
$this->assertNotEmpty($bucket['body']['$id']);
$this->assertEquals('zstd', $bucket['body']['compression']);
$bucketId = $bucket['body']['$id'];
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'fileId' => ID::unique(),
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'),
'permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]);
$this->assertEquals(201, $file['headers']['status-code']);
$this->assertNotEmpty($file['body']['$id']);
$this->assertEquals(true, DateTime::isValid($file['body']['$createdAt']));
$this->assertEquals('logo.png', $file['body']['name']);
$this->assertEquals('image/png', $file['body']['mimeType']);
$this->assertEquals(47218, $file['body']['sizeOriginal']);
$this->assertTrue(md5_file(realpath(__DIR__ . '/../../../resources/logo.png')) != $file['body']['signature']); // should validate that the file is encrypted
return ['bucketId' => $bucketId];
}
/**
* @depends testCreateBucketFile
*/
@ -598,6 +647,50 @@ trait StorageBase
return $data;
}
/**
* @depends testCreateBucketFileZstdCompression
*/
public function testFilePreviewZstdCompression(array $data): array
{
$bucketId = $data['bucketId'];
$file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'fileId' => ID::unique(),
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'),
'permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]);
$this->assertEquals(201, $file['headers']['status-code']);
$this->assertNotEmpty($file['body']['$id']);
$fileId = $file['body']['$id'];
//get image preview
$file3 = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId . '/preview', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'width' => 300,
'height' => 100,
'borderRadius' => '50',
'opacity' => '0.5',
'output' => 'png',
'rotation' => '45',
]);
$this->assertEquals(200, $file3['headers']['status-code']);
$this->assertEquals('image/png', $file3['headers']['content-type']);
$this->assertNotEmpty($file3['body']);
return $data;
}
/**
* @depends testCreateBucketFile
*/