lib/record-patch-builder.js
function validatePatchOperationValue(
	recordTypes, opType, opInd, pathPtr, val, forUpdate) {

	// error function
	const validate = errMsg => {
		if (errMsg)
			throw new common.X2SyntaxError(
				`Invalid value in patch operation #${opInd + 1} (${opType}):` +
					` ${errMsg}`);
	};

	// check if we have the value
	if (val === undefined)
		validate('no value is provided for the operation.');

	// get target property descriptor
	const propDesc = pathPtr.propDesc;

	// "merge" operation is a special case
	if (opType === 'merge') {

		// value must be an object
		if (((typeof val) !== 'object') || (val === null))
			validate('merge value must be a non-null object.');

		// target must be a single object or a whole map
		if (!(propDesc.isMap() && !pathPtr.collectionElement) &&
			!((propDesc.scalarValueType === 'object') && (
				propDesc.isScalar() || pathPtr.collectionElement)))
			validate('invalid merge target record element type.');

		// valid value, return it
		return val;
	}

	// validate if null is acceptable
	if (val === null) {
		if ((propDesc.isScalar() || !pathPtr.collectionElement) &&
			!propDesc.optional)
			validate('null for required property.');
		if (pathPtr.collectionElement && (propDesc.scalarValueType === 'object'))
			validate('null for nested object collection element.');
		return val; // valid
	}

	// validate depending on the property type
	if (propDesc.isArray() && !pathPtr.collectionElement) {
		if (!Array.isArray(val))
			validate('expected an array.');
		if (!propDesc.optional && (val.length === 0))
			validate('empty array for required property.');
		val.forEach(v => {
			validate(isInvalidScalarValueType(
				recordTypes, v, propDesc, forUpdate));
		});
	} else if (propDesc.isMap() && !pathPtr.collectionElement) {
		if ((typeof val) !== 'object')
			validate('expected an object.');
		const keys = Object.keys(val);
		if (!propDesc.optional && (keys.length === 0))
			validate('empty object for required property.');
		keys.forEach(k => {
			validate(isInvalidScalarValueType(
				recordTypes, val[k], propDesc, forUpdate));
		});
	} else {
		validate(isInvalidScalarValueType(
			recordTypes, val, propDesc, forUpdate));
	}

	// the value is valid, return it
	return val;
}
function validatePatchOperationValue(
	recordTypes, opType, opInd, pathPtr, val, forUpdate) {

	// error function
	const validate = errMsg => {
		if (errMsg)
			throw new common.X2SyntaxError(
				`Invalid value in patch operation #${opInd + 1} (${opType}):` +
					` ${errMsg}`);
	};

	// check if we have the value
	if (val === undefined)
		validate('no value is provided for the operation.');

	// get target property descriptor
	const propDesc = pathPtr.propDesc;

	// "merge" operation is a special case
	if (opType === 'merge') {

		// value must be an object
		if (((typeof val) !== 'object') || (val === null))
			validate('merge value must be a non-null object.');

		// target must be a single object or a whole map
		if (!(propDesc.isMap() && !pathPtr.collectionElement) &&
			!((propDesc.scalarValueType === 'object') && (
				propDesc.isScalar() || pathPtr.collectionElement)))
			validate('invalid merge target record element type.');

		// valid value, return it
		return val;
	}

	// validate if null is acceptable
	if (val === null) {
		if ((propDesc.isScalar() || !pathPtr.collectionElement) &&
			!propDesc.optional)
			validate('null for required property.');
		if (pathPtr.collectionElement && (propDesc.scalarValueType === 'object'))
			validate('null for nested object collection element.');
		return val; // valid
	}

	// validate depending on the property type
	if (propDesc.isArray() && !pathPtr.collectionElement) {
		if (!Array.isArray(val))
			validate('expected an array.');
		if (!propDesc.optional && (val.length === 0))
			validate('empty array for required property.');
		val.forEach(v => {
			validate(isInvalidScalarValueType(
				recordTypes, v, propDesc, forUpdate));
		});
	} else if (propDesc.isMap() && !pathPtr.collectionElement) {
		if ((typeof val) !== 'object')
			validate('expected an object.');
		const keys = Object.keys(val);
		if (!propDesc.optional && (keys.length === 0))
			validate('empty object for required property.');
		keys.forEach(k => {
			validate(isInvalidScalarValueType(
				recordTypes, val[k], propDesc, forUpdate));
		});
	} else {
		validate(isInvalidScalarValueType(
			recordTypes, val, propDesc, forUpdate));
	}

	// the value is valid, return it
	return val;
}
function validatePatchOperationValue ( recordTypes , opType , opInd , pathPtr , val , forUpdate ) { // error function const validate = errMsg => { if ( errMsg ) throw new common . X2SyntaxError ( ` ${ opInd + 1 } ${ opType } ` + ` ${ errMsg } ` ) ; } ; // check if we have the value if ( val === undefined ) validate ( 'no value is provided for the operation.' ) ; // get target property descriptor const propDesc = pathPtr . propDesc ; // "merge" operation is a special case if ( opType === 'merge' ) { // value must be an object if ( ( ( typeof val ) !== 'object' ) || ( val === null ) ) validate ( 'merge value must be a non-null object.' ) ; // target must be a single object or a whole map if ( ! ( propDesc . isMap ( ) && ! pathPtr . collectionElement ) && ! ( ( propDesc . scalarValueType === 'object' ) && ( propDesc . isScalar ( ) || pathPtr . collectionElement ) ) ) validate ( 'invalid merge target record element type.' ) ; // valid value, return it return val ; } // validate if null is acceptable if ( val === null ) { if ( ( propDesc . isScalar ( ) || ! pathPtr . collectionElement ) && ! propDesc . optional ) validate ( 'null for required property.' ) ; if ( pathPtr . collectionElement && ( propDesc . scalarValueType === 'object' ) ) validate ( 'null for nested object collection element.' ) ; return val ; // valid } // validate depending on the property type if ( propDesc . isArray ( ) && ! pathPtr . collectionElement ) { if ( ! Array . isArray ( val ) ) validate ( 'expected an array.' ) ; if ( ! propDesc . optional && ( val . length === 0 ) ) validate ( 'empty array for required property.' ) ; val . forEach ( v => { validate ( isInvalidScalarValueType ( recordTypes , v , propDesc , forUpdate ) ) ; } ) ; } else if ( propDesc . isMap ( ) && ! pathPtr . collectionElement ) { if ( ( typeof val ) !== 'object' ) validate ( 'expected an object.' ) ; const keys = Object . keys ( val ) ; if ( ! propDesc . optional && ( keys . length === 0 ) ) validate ( 'empty object for required property.' ) ; keys . forEach ( k => { validate ( isInvalidScalarValueType ( recordTypes , val [ k ] , propDesc , forUpdate ) ) ; } ) ; } else { validate ( isInvalidScalarValueType ( recordTypes , val , propDesc , forUpdate ) ) ; } // the value is valid, return it return val ; }
Validate value provided with a patch operation.

@private
@param {module:x2node-records~RecordTypesLibrary} recordTypes Record types
library.
@param {string} opType Patch operation type.
@param {number} opInd Index of the patch operation in the list of operations.
@param {module:x2node-pointers~RecordElementPointer} pathPtr Information
object for the property path where the value is supposed to belong.
@param {*} val The value to test. Can be <code>null</code>, but not
<code>undefined</code>.
@param {boolean} forUpdate <code>true</code> if the value is intended as a new
value for the property, or <code>false</code> if only used to test the current
property value.
@returns {*} The value passed in as <code>val</code>.
@throws {module:x2node-common.X2SyntaxError} If the value is invalid.
Validate value provided with a patch operation .