// Copyright (C) 2019-2022 Intel Corporation // // SPDX-License-Identifier: MIT /** * External API which should be used by for development * @module API */ function build() { const PluginRegistry = require('./plugins'); const loggerStorage = require('./logger-storage'); const Log = require('./log'); const ObjectState = require('./object-state'); const Statistics = require('./statistics'); const Comment = require('./comment'); const Issue = require('./issue'); const { Job, Task } = require('./session'); const { Project } = require('./project'); const implementProject = require('./project-implementation'); const { Attribute, Label } = require('./labels'); const MLModel = require('./ml-model'); const { FrameData } = require('./frames'); const { CloudStorage } = require('./cloud-storage'); const Organization = require('./organization'); const enums = require('./enums'); const { Exception, ArgumentError, DataError, ScriptingError, PluginError, ServerError, } = require('./exceptions'); const User = require('./user'); const pjson = require('../package.json'); const config = require('./config'); /** * API entrypoint * @namespace cvat * @memberof module:API */ const cvat = { /** * Namespace is used for an interaction with a server * @namespace server * @package * @memberof module:API.cvat */ server: { /** * @typedef {Object} ServerInfo * @property {string} name A name of the tool * @property {string} description A description of the tool * @property {string} version A version of the tool * @global */ /** * Method returns some information about the annotation tool * @method about * @async * @memberof module:API.cvat.server * @return {ServerInfo} * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async about() { const result = await PluginRegistry.apiWrapper(cvat.server.about); return result; }, /** * @typedef {Object} FileInfo * @property {string} name A name of a file * @property {module:API.cvat.enums.ShareFileType} type * A type of a file * @global */ /** * Method returns a list of files in a specified directory on a share * @method share * @async * @memberof module:API.cvat.server * @param {string} [directory=/] - Share directory path * @returns {FileInfo[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async share(directory = '/') { const result = await PluginRegistry.apiWrapper(cvat.server.share, directory); return result; }, /** * Method returns available annotation formats * @method formats * @async * @memberof module:API.cvat.server * @returns {module:API.cvat.classes.AnnotationFormats} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async formats() { const result = await PluginRegistry.apiWrapper(cvat.server.formats); return result; }, /** * Method returns user agreements that the user must accept * @method userAgreements * @async * @memberof module:API.cvat.server * @returns {Object[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async userAgreements() { const result = await PluginRegistry.apiWrapper(cvat.server.userAgreements); return result; }, /** * Method allows to register on a server * @method register * @async * @memberof module:API.cvat.server * @param {string} username An username for the new account * @param {string} firstName A first name for the new account * @param {string} lastName A last name for the new account * @param {string} email A email address for the new account * @param {string} password1 A password for the new account * @param {string} password2 The confirmation password for the new account * @param {Object} userConfirmations An user confirmations of terms of use if needed * @returns {Object} response data * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async register(username, firstName, lastName, email, password1, password2, userConfirmations) { const result = await PluginRegistry.apiWrapper( cvat.server.register, username, firstName, lastName, email, password1, password2, userConfirmations, ); return result; }, /** * Method allows to login on a server * @method login * @async * @memberof module:API.cvat.server * @param {string} username An username of an account * @param {string} password A password of an account * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async login(username, password) { const result = await PluginRegistry.apiWrapper(cvat.server.login, username, password); return result; }, /** * Method allows to logout from the server * @method logout * @async * @memberof module:API.cvat.server * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async logout() { const result = await PluginRegistry.apiWrapper(cvat.server.logout); return result; }, /** * Method allows to change user password * @method changePassword * @async * @memberof module:API.cvat.server * @param {string} oldPassword Current password for the account * @param {string} newPassword1 New password for the account * @param {string} newPassword2 Confirmation password for the account * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async changePassword(oldPassword, newPassword1, newPassword2) { const result = await PluginRegistry.apiWrapper( cvat.server.changePassword, oldPassword, newPassword1, newPassword2, ); return result; }, /** * Method allows to reset user password * @method requestPasswordReset * @async * @memberof module:API.cvat.server * @param {string} email A email address for the account * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async requestPasswordReset(email) { const result = await PluginRegistry.apiWrapper(cvat.server.requestPasswordReset, email); return result; }, /** * Method allows to confirm reset user password * @method resetPassword * @async * @memberof module:API.cvat.server * @param {string} newPassword1 New password for the account * @param {string} newPassword2 Confirmation password for the account * @param {string} uid User id * @param {string} token Request authentication token * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async resetPassword(newPassword1, newPassword2, uid, token) { const result = await PluginRegistry.apiWrapper( cvat.server.resetPassword, newPassword1, newPassword2, uid, token, ); return result; }, /** * Method allows to know whether you are authorized on the server * @method authorized * @async * @memberof module:API.cvat.server * @returns {boolean} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async authorized() { const result = await PluginRegistry.apiWrapper(cvat.server.authorized); return result; }, /** * Method allows to do requests via cvat-core with authorization headers * @method request * @async * @memberof module:API.cvat.server * @param {string} url * @param {Object} data request parameters: method, headers, data, etc. * @returns {Object | undefined} response data if exist * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async request(url, data) { const result = await PluginRegistry.apiWrapper(cvat.server.request, url, data); return result; }, /** * Method returns apps that are installed on the server * @method installedApps * @async * @memberof module:API.cvat.server * @returns {Object} map {installedApp: boolean} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async installedApps() { const result = await PluginRegistry.apiWrapper(cvat.server.installedApps); return result; }, }, /** * Namespace is used for getting projects * @namespace projects * @memberof module:API.cvat */ projects: { /** * @typedef {Object} ProjectFilter * @property {string} name Check if name contains this value * @property {module:API.cvat.enums.ProjectStatus} status * Check if status contains this value * @property {number} id Check if id equals this value * @property {number} page Get specific page * (default REST API returns 20 projects per request. * In order to get more, it is need to specify next page) * @property {string} owner Check if owner user contains this value * @property {string} search Combined search of contains among all fields * @global */ /** * Method returns list of projects corresponding to a filter * @method get * @async * @memberof module:API.cvat.projects * @param {ProjectFilter} [filter={}] project filter * @returns {module:API.cvat.classes.Project[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async get(filter = {}) { const result = await PluginRegistry.apiWrapper(cvat.projects.get, filter); return result; }, /** * Method returns list of project names with project ids * corresponding to a search phrase * used for autocomplete field * @method searchNames * @async * @memberof module:API.cvat.projects * @param {string} [search = ''] search phrase * @param {number} [limit = 10] number of returning project names * @returns {module:API.cvat.classes.Project[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} * */ async searchNames(search = '', limit = 10) { const result = await PluginRegistry.apiWrapper(cvat.projects.searchNames, search, limit); return result; }, }, /** * Namespace is used for getting tasks * @namespace tasks * @memberof module:API.cvat */ tasks: { /** * @typedef {Object} TaskFilter * @property {string} name Check if name contains this value * @property {module:API.cvat.enums.TaskStatus} status * Check if status contains this value * @property {module:API.cvat.enums.TaskMode} mode * Check if mode contains this value * @property {number} id Check if id equals this value * @property {number} page Get specific page * (default REST API returns 20 tasks per request. * In order to get more, it is need to specify next page) * @property {number} projectId Check if project_id field contains this value * @property {string} owner Check if owner user contains this value * @property {string} assignee Check if assigneed contains this value * @property {string} search Combined search of contains among all fields * @global */ /** * Method returns list of tasks corresponding to a filter * @method get * @async * @memberof module:API.cvat.tasks * @param {TaskFilter} [filter={}] task filter * @returns {module:API.cvat.classes.Task[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async get(filter = {}) { const result = await PluginRegistry.apiWrapper(cvat.tasks.get, filter); return result; }, }, /** * Namespace is used for getting jobs * @namespace jobs * @memberof module:API.cvat */ jobs: { /** * @typedef {Object} JobFilter * Only one of fields is allowed simultaneously * @property {number} taskID filter all jobs of specific task * @property {number} jobID filter job with a specific id * @global */ /** * Method returns list of jobs corresponding to a filter * @method get * @async * @memberof module:API.cvat.jobs * @param {JobFilter} filter job filter * @returns {module:API.cvat.classes.Job[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async get(filter = {}) { const result = await PluginRegistry.apiWrapper(cvat.jobs.get, filter); return result; }, }, /** * Namespace is used for getting users * @namespace users * @memberof module:API.cvat */ users: { /** * @typedef {Object} UserFilter * @property {boolean} self get only self * @global */ /** * Method returns list of users corresponding to a filter * @method get * @async * @memberof module:API.cvat.users * @param {UserFilter} [filter={}] user filter * @returns {module:API.cvat.classes.User[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async get(filter = {}) { const result = await PluginRegistry.apiWrapper(cvat.users.get, filter); return result; }, }, /** * Namespace is used for plugin management * @namespace plugins * @memberof module:API.cvat */ plugins: { /** * @typedef {Object} Plugin * A plugin is a Javascript object. It must have properties are listed below.
* It also mustn't have property 'functions' which is used internally.
* You can expand any API method including class methods.
* In order to expand class method just use a class name * in a cvat space (example is listed below). * * @property {string} name A name of a plugin * @property {string} description A description of a plugin * Example plugin implementation listed below: * @example * plugin = { * name: 'Example Plugin', * description: 'This example plugin demonstrates how plugin system in CVAT works', * cvat: { * server: { * about: { * // Plugin adds some actions after executing the cvat.server.about() * // For example it adds a field with installed plugins to a result * // An argument "self" is a plugin itself * // An argument "result" is a return value of cvat.server.about() * // All next arguments are arguments of a wrapped function * // (in this case the wrapped function doesn't have any arguments) * async leave(self, result) { * result.plugins = await self.internal.getPlugins(); * // Note that a method leave must return "result" (changed or not) * // Otherwise API won't work as expected * return result; * }, * }, * }, * // In this example plugin also wraps a class method * classes: { * Job: { * prototype: { * annotations: { * put: { * // The first argument "self" is a plugin, like in a case above * // The second argument is an argument of the * // Job.annotations.put() * // It contains an array of objects to put * // In this sample we round objects coordinates and save them * enter(self, objects) { * for (const obj of objects) { * if (obj.type != 'tag') { * const points = obj.position.map((point) => { * const roundPoint = { * x: Math.round(point.x), * y: Math.round(point.y), * }; * return roundPoint; * }); * } * } * }, * }, * }, * }, * }, * }, * }, * // In general you can add any others members to your plugin * // Members below are only examples * internal: { * async getPlugins() { * // Collect information about installed plugins * const plugins = await cvat.plugins.list(); * return plugins.map((el) => { * return { * name: el.name, * description: el.description, * }; * }); * }, * }, * }; * @global */ /** * Method returns list of installed plugins * @method list * @async * @memberof module:API.cvat.plugins * @returns {Plugin[]} * @throws {module:API.cvat.exceptions.PluginError} */ async list() { const result = await PluginRegistry.apiWrapper(cvat.plugins.list); return result; }, /** * Install plugin to CVAT * @method register * @async * @memberof module:API.cvat.plugins * @param {Plugin} [plugin] plugin for registration * @throws {module:API.cvat.exceptions.PluginError} */ async register(plugin) { const result = await PluginRegistry.apiWrapper(cvat.plugins.register, plugin); return result; }, }, /** * Namespace is used for serverless functions management (mainly related with DL models) * @namespace lambda * @memberof module:API.cvat */ lambda: { /** * Method returns list of available serverless models * @method list * @async * @memberof module:API.cvat.lambda * @returns {module:API.cvat.classes.MLModel[]} * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async list() { const result = await PluginRegistry.apiWrapper(cvat.lambda.list); return result; }, /** * Run long-time request for a function on a specific task * @method run * @async * @memberof module:API.cvat.lambda * @param {module:API.cvat.classes.Task} task task to be annotated * @param {module:API.cvat.classes.MLModel} model model used to get annotation * @param {object} [args] extra arguments * @returns {string} requestID * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ArgumentError} */ async run(task, model, args) { const result = await PluginRegistry.apiWrapper(cvat.lambda.run, task, model, args); return result; }, /** * Run short-time request for a function on a specific task * @method call * @async * @memberof module:API.cvat.lambda * @param {module:API.cvat.classes.Task} task task to be annotated * @param {module:API.cvat.classes.MLModel} model model used to get annotation * @param {object} [args] extra arguments * @returns {object[]} annotations * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ArgumentError} */ async call(task, model, args) { const result = await PluginRegistry.apiWrapper(cvat.lambda.call, task, model, args); return result; }, /** * Cancel running of a serverless function for a specific task * @method cancel * @async * @memberof module:API.cvat.lambda * @param {string} requestID * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ArgumentError} */ async cancel(requestID) { const result = await PluginRegistry.apiWrapper(cvat.lambda.cancel, requestID); return result; }, /** * @callback onRequestStatusChange * @param {string} status * @param {number} progress * @param {string} [message] * @global */ /** * Listen for a specific request * @method listen * @async * @memberof module:API.cvat.lambda * @param {string} requestID * @param {onRequestStatusChange} onChange * @throws {module:API.cvat.exceptions.ArgumentError} * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async listen(requestID, onChange) { const result = await PluginRegistry.apiWrapper(cvat.lambda.listen, requestID, onChange); return result; }, /** * Get active lambda requests * @method requests * @async * @memberof module:API.cvat.lambda * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async requests() { const result = await PluginRegistry.apiWrapper(cvat.lambda.requests); return result; }, }, /** * Namespace to working with logs * @namespace logger * @memberof module:API.cvat */ /** * Method to logger configuration * @method configure * @memberof module:API.cvat.logger * @param {function} isActiveChecker - callback to know if logger * should increase working time or not * @param {object} userActivityCallback - container for a callback
* Logger put here a callback to update user activity timer
* You can call it outside * @instance * @async * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ArgumentError} */ /** * Append log to a log collection
* Durable logs will have been added after "close" method is called for them
* Ignore rules exist for some logs (e.g. zoomImage, changeAttribute)
* Payload of ignored logs are shallowly combined to previous logs of the same type * @method log * @memberof module:API.cvat.logger * @param {module:API.cvat.enums.LogType | string} type - log type * @param {Object} [payload = {}] - any other data that will be appended to the log * @param {boolean} [wait = false] - specifies if log is durable * @returns {module:API.cvat.classes.Log} * @instance * @async * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ArgumentError} */ /** * Save accumulated logs on a server * @method save * @memberof module:API.cvat.logger * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} * @instance * @async */ logger: loggerStorage, /** * Namespace contains some changeable configurations * @namespace config * @memberof module:API.cvat */ config: { /** * @memberof module:API.cvat.config * @property {string} backendAPI host with a backend api * @memberof module:API.cvat.config * @property {string} proxy Axios proxy settings. * For more details please read here * @memberof module:API.cvat.config * @property {string} origin ui URL origin * @memberof module:API.cvat.config * @property {number} uploadChunkSize max size of one data request in mb * @memberof module:API.cvat.config */ get backendAPI() { return config.backendAPI; }, set backendAPI(value) { config.backendAPI = value; }, get proxy() { return config.proxy; }, set proxy(value) { config.proxy = value; }, get origin() { return config.origin; }, set origin(value) { config.origin = value; }, get uploadChunkSize() { return config.uploadChunkSize; }, set uploadChunkSize(value) { config.uploadChunkSize = value; }, }, /** * Namespace contains some library information e.g. api version * @namespace client * @memberof module:API.cvat */ client: { /** * @property {string} version Client version. * Format: {major}.{minor}.{patch} *
  • A major number is changed after an API becomes * incompatible with a previous version *
  • A minor number is changed after an API expands *
  • A patch number is changed after an each build * @memberof module:API.cvat.client * @readonly */ version: `${pjson.version}`, }, /** * Namespace is used for access to enums * @namespace enums * @memberof module:API.cvat */ enums, /** * Namespace is used for access to exceptions * @namespace exceptions * @memberof module:API.cvat */ exceptions: { Exception, ArgumentError, DataError, ScriptingError, PluginError, ServerError, }, /** * Namespace is used for getting cloud storages * @namespace cloudStorages * @memberof module:API.cvat */ cloudStorages: { /** * @typedef {Object} CloudStorageFilter * @property {string} displayName Check if displayName contains this value * @property {string} resource Check if resource name contains this value * @property {module:API.cvat.enums.ProviderType} providerType Check if providerType equal this value * @property {number} id Check if id equals this value * @property {number} page Get specific page * (default REST API returns 20 clouds storages per request. * In order to get more, it is need to specify next page) * @property {string} owner Check if an owner name contains this value * @property {string} search Combined search of contains among all the fields * @global */ /** * Method returns a list of cloud storages corresponding to a filter * @method get * @async * @memberof module:API.cvat.cloudStorages * @param {CloudStorageFilter} [filter={}] cloud storage filter * @returns {module:API.cvat.classes.CloudStorage[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async get(filter = {}) { const result = await PluginRegistry.apiWrapper(cvat.cloudStorages.get, filter); return result; }, }, /** * This namespace could be used to get organizations list from the server * @namespace organizations * @memberof module:API.cvat */ organizations: { /** * Method returns a list of organizations * @method get * @async * @memberof module:API.cvat.organizations * @returns {module:API.cvat.classes.Organization[]} * @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.ServerError} */ async get() { const result = await PluginRegistry.apiWrapper(cvat.organizations.get); return result; }, /** * Method activates organization context * @method activate * @async * @param {module:API.cvat.classes.Organization} * @memberof module:API.cvat.organizations * @throws {module:API.cvat.exceptions.ArgumentError} * @throws {module:API.cvat.exceptions.PluginError} */ async activate(organization) { const result = await PluginRegistry.apiWrapper(cvat.organizations.activate, organization); return result; }, /** * Method deactivates organization context * @method deactivate * @async * @memberof module:API.cvat.organizations * @throws {module:API.cvat.exceptions.PluginError} */ async deactivate() { const result = await PluginRegistry.apiWrapper(cvat.organizations.deactivate); return result; }, }, /** * Namespace is used for access to classes * @namespace classes * @memberof module:API.cvat */ classes: { User, Project: implementProject(Project), Task, Job, Log, Attribute, Label, Statistics, ObjectState, MLModel, Comment, Issue, FrameData, CloudStorage, Organization, }, }; cvat.server = Object.freeze(cvat.server); cvat.projects = Object.freeze(cvat.projects); cvat.tasks = Object.freeze(cvat.tasks); cvat.jobs = Object.freeze(cvat.jobs); cvat.users = Object.freeze(cvat.users); cvat.plugins = Object.freeze(cvat.plugins); cvat.lambda = Object.freeze(cvat.lambda); cvat.client = Object.freeze(cvat.client); cvat.enums = Object.freeze(cvat.enums); cvat.cloudStorages = Object.freeze(cvat.cloudStorages); cvat.organizations = Object.freeze(cvat.organizations); const implementAPI = require('./api-implementation'); Math.clamp = function clamp(value, min, max) { return Math.min(Math.max(value, min), max); }; const implemented = Object.freeze(implementAPI(cvat)); return implemented; } module.exports = build();