@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
206 lines (204 loc) • 7.49 kB
JavaScript
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