You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

512 lines
20 KiB
TypeScript

// Copyright (C) 2021-2022 Intel Corporation
//
// SPDX-License-Identifier: MIT
(() => {
const PluginRegistry = require('./plugins');
const serverProxy = require('./server-proxy');
const { isBrowser, isNode } = require('browser-or-node');
const { ArgumentError } = require('./exceptions');
const { CloudStorageCredentialsType, CloudStorageProviderType } = require('./enums');
function validateNotEmptyString(value) {
if (typeof value !== 'string') {
throw new ArgumentError(`Value must be a string. ${typeof value} was found`);
} else if (!value.trim().length) {
throw new ArgumentError('Value mustn\'t be empty string');
}
}
/**
* Class representing a cloud storage
* @memberof module:API.cvat.classes
*/
class CloudStorage {
constructor(initialData) {
const data = {
id: undefined,
display_name: undefined,
description: undefined,
credentials_type: undefined,
provider_type: undefined,
resource: undefined,
account_name: undefined,
key: undefined,
secret_key: undefined,
session_token: undefined,
key_file: undefined,
specific_attributes: undefined,
owner: undefined,
created_date: undefined,
updated_date: undefined,
manifest_path: undefined,
manifests: undefined,
};
for (const property in data) {
if (Object.prototype.hasOwnProperty.call(data, property) && property in initialData) {
data[property] = initialData[property];
}
}
Object.defineProperties(
this,
Object.freeze({
/**
* @name id
* @type {number}
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
*/
id: {
get: () => data.id,
},
/**
* Storage name
* @name displayName
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
displayName: {
get: () => data.display_name,
set: (value) => {
validateNotEmptyString(value);
data.display_name = value;
},
},
/**
* Storage description
* @name description
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
description: {
get: () => data.description,
set: (value) => {
if (typeof value !== 'string') {
throw new ArgumentError('Value must be string');
}
data.description = value;
},
},
/**
* Azure account name
* @name accountName
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
accountName: {
get: () => data.account_name,
set: (value) => {
validateNotEmptyString(value);
data.account_name = value;
},
},
/**
* AWS access key id
* @name accessKey
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
accessKey: {
get: () => data.key,
set: (value) => {
validateNotEmptyString(value);
data.key = value;
},
},
/**
* AWS secret key
* @name secretKey
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
secretKey: {
get: () => data.secret_key,
set: (value) => {
validateNotEmptyString(value);
data.secret_key = value;
},
},
/**
* Session token
* @name token
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
token: {
get: () => data.session_token,
set: (value) => {
validateNotEmptyString(value);
data.session_token = value;
},
},
/**
* Key file
* @name keyFile
* @type {File}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
keyFile: {
get: () => data.key_file,
set: (file) => {
if (file instanceof File) {
data.key_file = file;
} else {
throw new ArgumentError(`Should be a file. ${typeof file} was found`);
}
},
},
/**
* Unique resource name
* @name resource
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
resource: {
get: () => data.resource,
set: (value) => {
validateNotEmptyString(value);
data.resource = value;
},
},
/**
* @name manifestPath
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
manifestPath: {
get: () => data.manifest_path,
set: (value) => {
validateNotEmptyString(value);
data.manifest_path = value;
},
},
/**
* @name providerType
* @type {module:API.cvat.enums.ProviderType}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
providerType: {
get: () => data.provider_type,
set: (key) => {
if (key !== undefined && !!CloudStorageProviderType[key]) {
data.provider_type = CloudStorageProviderType[key];
} else {
throw new ArgumentError('Value must be one CloudStorageProviderType keys');
}
},
},
/**
* @name credentialsType
* @type {module:API.cvat.enums.CloudStorageCredentialsType}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
credentialsType: {
get: () => data.credentials_type,
set: (key) => {
if (key !== undefined && !!CloudStorageCredentialsType[key]) {
data.credentials_type = CloudStorageCredentialsType[key];
} else {
throw new ArgumentError('Value must be one CloudStorageCredentialsType keys');
}
},
},
/**
* @name specificAttributes
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
specificAttributes: {
get: () => data.specific_attributes,
set: (attributesValue) => {
if (typeof attributesValue === 'string') {
const attrValues = new URLSearchParams(
Array.from(new URLSearchParams(attributesValue).entries()).filter(
([key, value]) => !!key && !!value,
),
).toString();
if (!attrValues) {
throw new ArgumentError('Value must match the key1=value1&key2=value2');
}
data.specific_attributes = attributesValue;
} else {
throw new ArgumentError('Value must be a string');
}
},
},
/**
* Instance of a user who has created the cloud storage
* @name owner
* @type {module:API.cvat.classes.User}
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
*/
owner: {
get: () => data.owner,
},
/**
* @name createdDate
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
*/
createdDate: {
get: () => data.created_date,
},
/**
* @name updatedDate
* @type {string}
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
*/
updatedDate: {
get: () => data.updated_date,
},
/**
* @name manifests
* @type {string[]}
* @memberof module:API.cvat.classes.CloudStorage
* @instance
* @throws {module:API.cvat.exceptions.ArgumentError}
*/
manifests: {
get: () => data.manifests,
set: (manifests) => {
if (Array.isArray(manifests)) {
for (const elem of manifests) {
if (typeof elem !== 'string') {
throw new ArgumentError('Each element of the manifests array must be a string');
}
}
data.manifests = manifests;
} else {
throw new ArgumentError('Value must be an array');
}
},
},
}),
);
}
/**
* Method updates data of a created cloud storage or creates new cloud storage
* @method save
* @returns {module:API.cvat.classes.CloudStorage}
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
* @async
* @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.PluginError}
*/
async save() {
const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.save);
return result;
}
/**
* Method deletes a cloud storage from a server
* @method delete
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
* @async
* @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.PluginError}
*/
async delete() {
const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.delete);
return result;
}
/**
* Method returns cloud storage content
* @method getContent
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
* @async
* @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.PluginError}
*/
async getContent() {
const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.getContent);
return result;
}
/**
* Method returns the cloud storage preview
* @method getPreview
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
* @async
* @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.PluginError}
*/
async getPreview() {
const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.getPreview);
return result;
}
/**
* Method returns cloud storage status
* @method getStatus
* @memberof module:API.cvat.classes.CloudStorage
* @readonly
* @instance
* @async
* @throws {module:API.cvat.exceptions.ServerError}
* @throws {module:API.cvat.exceptions.PluginError}
*/
async getStatus() {
const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.getStatus);
return result;
}
}
CloudStorage.prototype.save.implementation = async function () {
function prepareOptionalFields(cloudStorageInstance) {
const data = {};
if (cloudStorageInstance.description !== undefined) {
data.description = cloudStorageInstance.description;
}
if (cloudStorageInstance.accountName) {
data.account_name = cloudStorageInstance.accountName;
}
if (cloudStorageInstance.accessKey) {
data.key = cloudStorageInstance.accessKey;
}
if (cloudStorageInstance.secretKey) {
data.secret_key = cloudStorageInstance.secretKey;
}
if (cloudStorageInstance.token) {
data.session_token = cloudStorageInstance.token;
}
if (cloudStorageInstance.keyFile) {
data.key_file = cloudStorageInstance.keyFile;
}
if (cloudStorageInstance.specificAttributes !== undefined) {
data.specific_attributes = cloudStorageInstance.specificAttributes;
}
return data;
}
// update
if (typeof this.id !== 'undefined') {
// provider_type and recource should not change;
// send to the server only the values that have changed
const initialData = {};
if (this.displayName) {
initialData.display_name = this.displayName;
}
if (this.credentialsType) {
initialData.credentials_type = this.credentialsType;
}
if (this.manifests) {
initialData.manifests = this.manifests;
}
const cloudStorageData = {
...initialData,
...prepareOptionalFields(this),
};
await serverProxy.cloudStorages.update(this.id, cloudStorageData);
return this;
}
// create
const initialData = {
display_name: this.displayName,
credentials_type: this.credentialsType,
provider_type: this.providerType,
resource: this.resource,
manifests: this.manifests,
};
const cloudStorageData = {
...initialData,
...prepareOptionalFields(this),
};
const cloudStorage = await serverProxy.cloudStorages.create(cloudStorageData);
return new CloudStorage(cloudStorage);
};
CloudStorage.prototype.delete.implementation = async function () {
const result = await serverProxy.cloudStorages.delete(this.id);
return result;
};
CloudStorage.prototype.getContent.implementation = async function () {
const result = await serverProxy.cloudStorages.getContent(this.id, this.manifestPath);
return result;
};
CloudStorage.prototype.getPreview.implementation = async function getPreview() {
return new Promise((resolve, reject) => {
serverProxy.cloudStorages
.getPreview(this.id)
.then((result) => {
if (isNode) {
resolve(global.Buffer.from(result, 'binary').toString('base64'));
} else if (isBrowser) {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(result);
}
})
.catch((error) => {
reject(error);
});
});
};
CloudStorage.prototype.getStatus.implementation = async function () {
const result = await serverProxy.cloudStorages.getStatus(this.id);
return result;
};
module.exports = {
CloudStorage,
};
})();