UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

206 lines (204 loc) 7.49 kB
import { throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { LogLevel } from '../diagnostics/log-level'; import { Logging } from '../diagnostics/logging'; /** * Defines an object that can be upgraded from older versions to the current version upon initialization. */ export class VersionedObject { handlers; gatewayService; get logSourceName() { return 'VersionedObject'; } /** * The current version of the object */ currentVersion; /** * The properties of the object */ properties; /** * Gets an initialized empty versioned object wrapper */ static getEmptyWrapper() { return { version: null, properties: {} }; } /** * Returns an empty versioned object if the passed in object is not correctly versioned. * Otherwise, returns the passed in object. */ static ensureIsVersionedObject(obj) { if (!obj || MsftSme.isNullOrUndefined(obj.version)) { return VersionedObject.getEmptyWrapper(); } return obj; } /** * Initializes a new instance of a VersionedObject * If the current version of the object is less than the latest version, * then 'upgrade()' will be called until the version is updated to the latest version. * An error will be thrown if upgrade is called and the version is not moved forward by at least 1. * @param objectWrapper the simplified version of the plain object with versioning * @param handlers The handlers to modify the plain Object */ constructor(objectWrapper, handlers, gatewayService) { this.handlers = handlers; this.gatewayService = gatewayService; this.initialize(objectWrapper, handlers); } /** * Initializes this versioned object * @param objectWrapper the simplified version of the plain object with versioning * @param handlers The handlers to modify the plain Object */ initialize(objectWrapper, handlers) { // verify arguments if (MsftSme.isNullOrUndefined(objectWrapper) || MsftSme.isNullOrUndefined(objectWrapper.properties) || MsftSme.isNullOrUndefined(handlers)) { Logging.log({ level: LogLevel.Error, message: `${this.logSourceName} Invalid Arguments: objectWrapper: ${objectWrapper}, handlers: ${handlers}`, params: { latestVersion: this.latestVersion, objectType: this.logSourceName }, source: 'VersionedObject.ctor' }); return; } // save version and properties this.currentVersion = objectWrapper.version; this.properties = MsftSme.deepCopy(objectWrapper.properties); // ensure that the getter for latest version has been defined if (MsftSme.isNullOrUndefined(this.latestVersion)) { Logging.log({ level: LogLevel.Error, message: `${this.logSourceName} does not properly extend VersionedObject. latestVersion getter is ${this.latestVersion}'`, params: { latestVersion: this.latestVersion, objectType: this.logSourceName }, source: 'VersionedObject.ctor' }); return; } let prevVersion = MsftSme.isNullOrUndefined(this.currentVersion) ? -1 : this.currentVersion; // upgrade the current version until it is the latest version while (MsftSme.isNullOrUndefined(this.currentVersion) || this.currentVersion < this.latestVersion) { // upgrade the object this.upgrade(); // check if upgrade succeeded (did not downgrade and did not upgrade past latest version) if (prevVersion >= this.currentVersion || this.currentVersion > this.latestVersion) { // upgrade didnt work as intended as the version is now invalid. Logging.log({ level: LogLevel.Error, message: `Calling 'upgrade()' did not upgrade the object correctly'`, params: { previousVersion: prevVersion, currentVersion: this.currentVersion, upgradingToVersion: this.latestVersion, objectType: this.logSourceName }, source: 'VersionedObject.ctor' }); // stop trying to upgrade break; } // remember the version before cycling again prevVersion = this.currentVersion; } } /** * Converts this versioned object to its pure json representation */ toJson() { return { properties: this.properties, version: this.currentVersion }; } /** * Saves the current properties */ save() { return this.handlers.save(this.toJson()); } /** * Attempts to save the properties after executing a function. * If saving fails, the properties is reverted to its previous state before emitting the error */ trySave(fn) { const backup = Object.assign({}, this.properties); fn(); return this.save() .pipe(catchError((error) => { Object.assign(this.properties, backup); // rethrow the error return throwError(() => error); })); } /** * Clears the current properties */ clear() { this.properties = {}; } /** * Clears a specific value from the setting. * @param key a property key */ clearProperty(key) { if (!MsftSme.isNullOrUndefined(key) && !MsftSme.isNullOrUndefined(this.properties) && !MsftSme.isNullOrUndefined(!this.properties[key])) { delete this.properties[key]; return true; } else { return false; } } /** * Gets a property from 'properties' * @param key the property key * @returns the properties value */ getProperty(key) { if (!MsftSme.isNullOrUndefined(this.properties)) { return this.properties[key]; } else { Logging.log({ level: LogLevel.Error, message: `Could not find a property with the name: '${key}'. Please wait for object properties to be defined.`, params: { key: key, objectType: this.logSourceName }, source: 'VersionedObject.getProperty' }); } return null; } /** * Sets a property in 'properties' * @param key the property key * @param value the new value */ setProperty(key, value) { if (!MsftSme.isNullOrUndefined(this.properties)) { this.properties[key] = value; } else { Logging.log({ level: LogLevel.Error, message: `Could not find a property with the name: '${key}'. Please wait for object properties to be defined.`, params: { key: key, objectType: this.logSourceName }, source: 'VersionedObject.setProperty' }); } } } //# sourceMappingURL=versioned-object.js.map