@c8y/client
Version:
Client application programming interface to access the Cumulocity IoT-Platform REST services.
503 lines • 17.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationService = void 0;
const core_1 = require("../core");
const inventory_1 = require("../inventory");
const tenant_1 = require("../tenant");
const user_1 = require("../user");
const ApplicationBinaryService_1 = require("./ApplicationBinaryService");
const ApplicationType_1 = require("./ApplicationType");
const gettext_1 = require("../gettext");
class ApplicationService extends core_1.Service {
constructor() {
super(...arguments);
this.baseUrl = 'application';
this.listUrl = 'applications';
this.propertyName = 'applications';
this.channel = '/applications/*';
}
/**
* Creates a new application.
*
* @param {IIdentified} entity Application object.
*
* @returns Response wrapped in [[IResult]]
*
* **Example**
* ```typescript
*
* const newApp = {
* name: 'New application',
* type: 'EXTERNAL',
* key: 'new-app'
* };
*
* (async () => {
* const {data, res} = await applicationService.create(newApp);
* })();
* ```
*/
async create(entity) {
return super.create(entity);
}
/**
* Clones a given application. The application name, key, and context-path will be
* prefixed with `clone` and if necessary a number.
* @param entity The application to clone.
* @param version If a blueprint, you can define which version to clone. If not provided, it will always clone the latest version.
* @returns The application entity.
*/
async clone(entity, version) {
const url = `${this.getDetailUrl(entity)}/clone`;
const method = 'POST';
const body = '';
const headers = { 'content-type': 'application/json', accept: 'application/json' };
let params = undefined;
if (version) {
params = { version };
}
const res = await this.fetch(url, { method, body, headers, params });
const data = await res.json();
return { res, data };
}
/**
* Gets the list of existing applications filtered by parameters.
*
* @returns Response wrapped in [[IResultList]]
*
* @param {object} filter Object containing filters for querying applications.
*
* **Example**
* ```typescript
*
* const filter: object = {
* pageSize: 100,
* withTotalPages: true
* };
*
* (async () => {
* const {data, res, paging} = await applicationService.list(filter);
* })();
* ```
*/
async list(filter = {}) {
return super.list(filter);
}
/**
* Gets the list of all application versions.
*
* @param {string|number|IIdentified} entityOrId Entity or Id of the entity.
*
* @param {object} params Additional request parameters.
*
* @returns Returns list of all application versions.
*
* **Example**
* ```typescript
*
* const applicationId: number = 1;
*
* (async () => {
* const {res, data} = await applicationService.listVersions(applicationId);
* })();
* ```
*/
async listVersions(entityOrId, params = {}) {
const id = this.getEntityId(entityOrId);
const url = `${this.listUrl}/${id}/versions`;
const headers = { 'content-type': 'application/json' };
try {
const res = await this.fetch(url, { headers, params });
const data = (await res.json())?.applicationVersions;
return { res, data };
}
catch (ex) {
if (ex.res.status === 404) {
const { data: appDetail, res } = await this.detail(entityOrId);
return { res, data: appDetail.applicationVersions };
}
throw ex;
}
}
/**
* Gets the details of selected application.
*
* @param {string|number|IIdentified} entityOrId Entity or Id of the entity.
*
* @returns Response wrapped in [[IResult]]
*
* **Example**
* ```typescript
*
* const applicationId: number = 1;
*
* (async () => {
* const {data, res} = await applicationService.detail(applicationId);
* })();
* ```
*/
async detail(entityOrId) {
return super.detail(entityOrId);
}
/**
* Updates existing application.
* Make sure that you specifiy the application id within the update object.
*
* @param {IIdentified} entity Application object.
*
* @returns Response wrapped in [[IResult]]
*
* **Example**
* ```typescript
*
* const updateApp = {
* id: 38
* name: 'Updated application'
* };
*
* (async () => {
* const {data, res} = await applicationService.update(updateApp);
* })();
* ```
*/
async update(entity) {
return super.update(entity);
}
/**
* Removes an application with given id.
*
* @returns Response wrapped in [[IResult]]
*
* @param {string | number | IIdentified} entityOrId entity or id of the application.
*
* **Example**
* ```typescript
*
* const removeApp: object = {
* id: 38
* };
*
* (async () => {
* const {data, res} = await applicationService.delete(removeApp);
* // data will be null
* })();
* ```
*/
async delete(entityOrId) {
return super.delete(entityOrId);
}
async listByName(name, params = {}) {
const headers = { 'content-type': 'application/json' };
const url = `applicationsByName/${encodeURIComponent(name)}`;
const res = await this.fetch(url, { headers, params });
const json = await res.json();
const data = json[this.propertyName];
return { res, data };
}
async listByTenant(tenantOrName, params = {}) {
const headers = { 'content-type': 'application/json' };
const tenantService = new tenant_1.TenantService(this.client);
const tenantName = this.getIdString(tenantOrName || (await tenantService.current()).data.name);
const url = `applicationsByTenant/${encodeURIComponent(tenantName)}`;
const res = await this.fetch(url, { headers, params });
const json = await res.json();
const data = json[this.propertyName];
return { res, data };
}
async listByOwner(tenantOrName, params = {}) {
const headers = { 'content-type': 'application/json' };
const tenantService = new tenant_1.TenantService(this.client);
const tenantName = this.getIdString(tenantOrName || (await tenantService.current()).data.name);
const url = `applicationsByOwner/${encodeURIComponent(tenantName)}`;
const res = await this.fetch(url, { headers, params });
const json = await res.json();
const data = json[this.propertyName];
return { res, data };
}
async listByUser(userOrId, params = {}) {
const headers = { 'content-type': 'application/json' };
const userService = new user_1.UserService(this.client);
const userId = this.getIdString(userOrId || (await userService.current()).data);
const url = `applicationsByUser/${encodeURIComponent(userId)}`;
const res = await this.fetch(url, { headers, params });
const json = await res.json();
const data = json[this.propertyName];
return { res, data };
}
async reactivateArchive(appId) {
const url = `${this.listUrl}/${appId}/refresh`;
const method = 'POST';
const body = '';
const headers = { 'content-type': 'application/json', accept: 'application/json' };
const res = await this.fetch(url, { method, body, headers });
return { res, data: null };
}
binary(application) {
return new ApplicationBinaryService_1.ApplicationBinaryService(this.client, application);
}
getHref(application) {
if (application.type === ApplicationType_1.ApplicationType.EXTERNAL) {
return application.externalUrl;
}
return `/apps/${application.public ? 'public/' : ''}${application.contextPath}`;
}
/**
* Checks if current user can access specified application.
*
* @returns Response wrapped in [[IResult]]
*
* @param {string | IApplication} application Application name or contextPath as a
* string or Application object.
*
* **Example**
* ```typescript
*
* const checkApp: object = {
* name: 'myApplication'
* };
*
* (async () => {
* const {data, res} = await applicationService.isAvailable(checkApp);
* })();
* ```
*/
async isAvailable(application) {
const { res, data } = await this.listByUser(undefined, {
dropOverwrittenApps: true,
noPaging: true
});
const available = (data || []).some((availableApp) => typeof application === 'string'
? availableApp.name === application || availableApp.contextPath === application
: this.isMatch(availableApp, application));
return { data: available, res };
}
/**
* Gets instance details of the specified application (microservice).
*
* @param {string|number|IApplication} entityOrId Entity or Id of the application.
*
* @returns Response wrapped in [[IResultList]]
*
* **Example**
* ```typescript
*
* const applicationId: number = 1;
*
* (async () => {
* const {data, res} = await applicationService.getStatusDetails(applicationId);
* })();
* ```
*/
async getStatusDetails(entityOrId) {
const appId = this.getEntityId(entityOrId);
const inventory = new inventory_1.InventoryService(this.client, this.realtime);
return inventory.list({ type: `c8y_Application_${appId}` });
}
/**
* Extracts instance names of the provided IApplicationManagedObject.
*
* @param {IApplicationManagedObject} appStatusDetails Application details managedObject.
*
* @returns instance names
*
* **Example**
* ```typescript
*
* const applicationId: number = 1;
*
* (async () => {
* const {data, res} = await applicationService.getStatusDetails(applicationId);
* const instances = data.map((appMO) => applicationService.getInstanceNames(appMO));
* })();
* ```
*/
getInstanceNames(appStatusDetails) {
let instanceNames = new Array();
if (appStatusDetails && appStatusDetails.c8y_Status && appStatusDetails.c8y_Status.instances) {
instanceNames = Object.keys(appStatusDetails.c8y_Status.instances);
}
return instanceNames;
}
/**
* Get log for a specific application instance.
*
* @param {string|number|IApplication} entityOrId Entity or Id of the application.
*
* @param {string} instanceName instance name of the application.
*
* @param {IApplicationInstanceLogRequestParams} params Object containing parameters for querying the log file.
*
* @returns Response wrapped in [[IResult]]
*
* **Example**
* ```typescript
*
* const applicationId: number = 1;
* const applicationInstanceName: string = 'apama-ctrl-1c-4g-scope-t123456789-deployment-abcdefghij-abcde';
*
* (async () => {
* const {data, res} = await applicationService.getInstanceLog(applicationId, applicationInstanceName);
* })();
* ```
*/
async getInstanceLog(entityOrId, instanceName, params) {
const url = `${this.getDetailUrl(entityOrId)}/logs/${instanceName}`;
const headers = { accept: this.mimeType('applicationLogs') };
const res = await this.fetch(url, { headers, params });
const data = await res.json();
return { res, data };
}
/**
* Dynamic options are stored on the API in a specific `config: {}` object. They can
* be used to configure the app dynamically.
*
* Note: To avoids conflicts with the default Config, it is recommended
* to use a certain namespace.
* @param entityOrId Entity or Id of the application.
* @param config Configuration to be updated.
* @returns Returns updated configuration.
*/
async updateApplicationConfig(entityOrId, config) {
const id = this.getEntityId(entityOrId);
const { data: app } = await this.detail(id);
const currentConfig = app?.config || {};
const newConfig = { ...currentConfig, ...config };
const updatedConfigApp = await this.update({
id,
config: newConfig
});
return (await updatedConfigApp)?.data;
}
/**
* Gets manifest (cumulocity.json file) of a given application.
*
* @param {IApplication} app Application entity.
*
* @param {string} app version
*
* @returns Application manifest object.
*/
async getAppManifest(app, version) {
const date = new Date();
let result;
if (!version) {
result = await this.client.fetch(`/apps/${app.contextPath}/cumulocity.json?nocache=${date.getTime()}`);
}
else {
result = await this.client.fetch(`/apps/${app.contextPath}@${version}/cumulocity.json?nocache=${date.getTime()}`);
}
if (result.status >= 400) {
throw new Error((0, gettext_1.gettext)('No Cumulocity IoT manifest found.'));
}
const c8yJson = await result.json();
return c8yJson;
}
/**
* Updates manifest (cumulocity.json file) of a given application.
*
* @param {string|number|IApplication} entityOrId Entity or Id of the application.
*
* @param {any} manifestJSON Application manifest object to be stored.
*
* @returns Application manifest object.
*/
async storeAppManifest(entityOrId, manifestJSON) {
return await this.binary(entityOrId).updateFiles([
{ path: 'cumulocity.json', contents: JSON.stringify(manifestJSON) }
]);
}
/**
* Sets tags for specific application package version.
*
* @param {IApplication} app Application entity.
*
* @param {string} version Application package version which tags will be set.
*
* @param {string[]} tags Tags array to set on package version
*
* @returns Application version object.
*/
async setPackageVersionTag(app, version, tags) {
const url = `${this.getDetailUrl(app)}/versions/${version}`;
const method = 'PUT';
const body = JSON.stringify({ tags });
const headers = {
accept: 'application/vnd.com.nsn.cumulocity.applicationVersion+json;charset=UTF-8;ver=0.9',
'content-type': 'application/json'
};
const res = await this.fetch(url, { method, body, headers });
const data = await res.json();
return { res, data };
}
/**
* Retrieves the manifest of the application behind the given context path.
* @param contextPath
*/
async getManifestOfContextPath(contextPath) {
const url = `${this.getDetailUrl(contextPath)}/manifest`;
const res = await this.fetch(url);
const { application } = await res.json();
return {
res,
data: application
};
}
/**
* Removes package version.
*
* @param {IApplication} app Application entity.
*
* @param {IApplicationVersionDeleteParams} params Version or tag indication package to remove.
*
* @returns Request response.
*
* **Example**
* ```typescript
*
* const { res } = await applicationService.deleteVersionPackage(app, {version: '1.0.0'});
*
* const { res } = await applicationService.deleteVersionPackage(app, {tag: 'next'});
*
* ```
*/
async deleteVersionPackage(app, params) {
const url = `${this.getDetailUrl(app)}/versions/`;
const method = 'DELETE';
const res = await this.fetch(url, this.changeFetchOptions({ method, params }, url));
return { res, data: null };
}
/**
* Updates the availability of the given application to the provided value.
*
* @param {string|number|IApplication} entityOrId Entity or Id of the application.
*
* @param {any} availability The new application availability.
*
* @returns Updated application.
*/
async updateApplicationAvailability(entityOrId, availability) {
const id = this.getEntityId(entityOrId);
return await this.update({
id,
availability
});
}
isMatch(object, source) {
return Object.keys(source).every(key => {
if (Array.isArray(object[key]) && Array.isArray(source[key])) {
return source[key].every(el => object[key].includes(el));
}
else if (typeof object[key] === 'object' &&
object[key] !== null &&
typeof source[key] === 'object' &&
source[key] !== null) {
return this.isMatch(object[key], source[key]);
}
else {
return object[key] === source[key];
}
});
}
}
exports.ApplicationService = ApplicationService;
//# sourceMappingURL=ApplicationService.js.map