TransactionDescriptorProcessor.js

/**
 * Processes and looks up transaction descriptor properties.
 * @note This class is not intended to be used directly.
 */
export default class TransactionDescriptorProcessor {
	/**
	 * Creates a transaction descriptor processor.
	 * @param {object} transactionDescriptor Transaction descriptor.
	 * @param {Map<string, function>} typeParsingRules Type-dependent parsing rules.
	 * @param {function|undefined} typeConverter Converts a generated type to an sdk type (optional).
	 */
	constructor(transactionDescriptor, typeParsingRules, typeConverter = undefined) {
		/**
		 * @private
		 */
		this._transactionDescriptor = transactionDescriptor;

		/**
		 * @private
		 */
		this._typeParsingRules = typeParsingRules;

		/**
		 * Tries to coerce a value to a more appropriate type.
		 * @param {object} value Original value.
		 * @returns {object} Type converted value.
		 * @private
		 */
		this._typeConverter = typeConverter || (value => value);

		/**
		 * @private
		 */
		this._typeHints = {};
	}

	/**
	 * Looks up value and applies type hints.
	 * @param {string} key Key for which to retrieve value.
	 * @returns {object} Value corresponding to key.
	 * @private
	 */
	_lookupValueAndApplyTypeHints(key) {
		if (undefined === this._transactionDescriptor[key])
			throw RangeError(`transaction descriptor does not have attribute ${key}`);

		let value = this._transactionDescriptor[key];
		const typeHint = this._typeHints[key];
		const rule = this._typeParsingRules.get(typeHint);
		if (rule)
			value = rule(value);

		return value;
	}

	/**
	 * Looks up the value for key.
	 * @param {string} key Key for which to retrieve value.
	 * @returns {object} Value corresponding to key.
	 */
	lookupValue(key) {
		const value = this._lookupValueAndApplyTypeHints(key);
		return Array.isArray(value)
			? value.map(item => this._typeConverter(item))
			: this._typeConverter(value);
	}

	/**
	 * Copies all descriptor information to a transaction.
	 * @param {object} transaction Transaction to which to copy keys.
	 * @param {Array<string>|undefined} ignoreKeys Keys of descriptor values not to copy (optional).
	 */
	copyTo(transaction, ignoreKeys = undefined) {
		Object.getOwnPropertyNames(this._transactionDescriptor).forEach(key => {
			if (ignoreKeys && -1 !== ignoreKeys.indexOf(key))
				return;

			if (key.endsWith('Computed'))
				throw RangeError(`cannot explicitly set computed field ${key}`);

			if (undefined === transaction[key])
				throw RangeError(`transaction does not have attribute ${key}`);

			const value = this.lookupValue(key);
			transaction[key] = value;
		});
	}

	/**
	 * Sets type hints.
	 * @param {TypeHintsMap|undefined} typeHints New type hints. // eslint-disable-line valid-jsdoc
	 */
	setTypeHints(typeHints) {
		this._typeHints = typeHints || {};
	}
}

// region type declarations

/**
 * Type hints map.
 * @class
 * @typedef {{[key: string]: string}} TypeHintsMap
 */

// endregion