function validate(val, affectedKey, affectedKeyGeneric, def, op, isInArrayItemObject, isInSubObject) {
    // Get the schema for this key, marking invalid if there isn't one.
    if (!def) {
      // We don't need KEY_NOT_IN_SCHEMA error for $unset and we also don't need to continue
      if (op === '$unset' || (op === '$currentDate' && affectedKey.endsWith('.$type'))) return;

      validationErrors.push({
        name: affectedKey,
        type: SimpleSchema.ErrorTypes.KEY_NOT_IN_SCHEMA,
        value: val,
      });
      return;
    }

    // For $rename, make sure that the new name is allowed by the schema
    if (op === '$rename' && !schema.allowsKey(val)) {
      validationErrors.push({
        name: val,
        type: SimpleSchema.ErrorTypes.KEY_NOT_IN_SCHEMA,
        value: null,
      });
      return;
    }

    // Prepare the context object for the validator functions
    const fieldParentNameWithEndDot = getParentOfKey(affectedKey, true);
    const fieldParentName = fieldParentNameWithEndDot.slice(0, -1);

    const fieldValidationErrors = [];

    const validatorContext = {
      addValidationErrors(errors) {
        errors.forEach((error) => fieldValidationErrors.push(error));
      },
      field(fName) {
        return getFieldInfo(fName);
      },
      genericKey: affectedKeyGeneric,
      isInArrayItemObject,
      isInSubObject,
      isModifier,
      isSet: (val !== undefined),
      key: affectedKey,
      obj,
      operator: op,
      parentField() {
        return getFieldInfo(fieldParentName);
      },
      siblingField(fName) {
        return getFieldInfo(fieldParentNameWithEndDot + fName);
      },
      validationContext,
      value: val,
      // Value checks are not necessary for null or undefined values, except
      // for non-optional null array items, or for $unset or $rename values
      valueShouldBeChecked: (
        op !== '$unset' && op !== '$rename'
        && ((val !== undefined && val !== null) || (affectedKeyGeneric.slice(-2) === '.$' && val === null && !def.optional))
      ),
      ...(extendedCustomContext || {}),
    };

    const builtInValidators = [
      requiredValidator,
      typeValidator,
      allowedValuesValidator,
    ];
    const validators = builtInValidators
      .concat(schema._validators)
      .concat(SimpleSchema._validators);

    // Loop through each of the definitions in the SimpleSchemaGroup.
    // If any return true, we're valid.
    const fieldIsValid = def.type.some((typeDef) => {
      // If the type is SimpleSchema.Any, then it is valid:
      if (typeDef === SimpleSchema.Any) return true;

      const { type, ...definitionWithoutType } = def; // eslint-disable-line no-unused-vars

      const finalValidatorContext = {
        ...validatorContext,

        // Take outer definition props like "optional" and "label"
        // and add them to inner props like "type" and "min"
        definition: {
          ...definitionWithoutType,
          ...typeDef,
        },
      };

      // Add custom field validators to the list after the built-in
      // validators but before the schema and global validators.
      const fieldValidators = validators.slice(0);
      if (typeof typeDef.custom === 'function') {
        fieldValidators.splice(builtInValidators.length, 0, typeDef.custom);
      }

      // We use _.every just so that we don't continue running more validator
      // functions after the first one returns false or an error string.
      return fieldValidators.every((validator) => {
        const result = validator.call(finalValidatorContext);

        // If the validator returns a string, assume it is the
        // error type.
        if (typeof result === 'string') {
          fieldValidationErrors.push({
            name: affectedKey,
            type: result,
            value: val,
          });
          return false;
        }

        // If the validator returns an object, assume it is an
        // error object.
        if (typeof result === 'object' && result !== null) {
          fieldValidationErrors.push({
            name: affectedKey,
            value: val,
            ...result,
          });
          return false;
        }

        // If the validator returns false, assume they already
        // called this.addValidationErrors within the function
        if (result === false) return false;

        // Any other return value we assume means it was valid
        return true;
      });
    });

    if (!fieldIsValid) {
      validationErrors = validationErrors.concat(fieldValidationErrors);
    }
  }
// Validation function called for each affected key
Validation function called for each affected key
Validation function called for each affected key
function validate(val, affectedKey, affectedKeyGeneric, def, op, isInArrayItemObject, isInSubObject) {
    if (!def) {
      if (op === '$unset' || (op === '$currentDate' && affectedKey.endsWith('.$type'))) return;
      validationErrors.push({
        name: affectedKey,
        type: SimpleSchema.ErrorTypes.KEY_NOT_IN_SCHEMA,
        value: val,
      });
      return;
    }
    if (op === '$rename' && !schema.allowsKey(val)) {
      validationErrors.push({
        name: val,
        type: SimpleSchema.ErrorTypes.KEY_NOT_IN_SCHEMA,
        value: null,
      });
      return;
    }
    const fieldParentNameWithEndDot = getParentOfKey(affectedKey, true);
    const fieldParentName = fieldParentNameWithEndDot.slice(0, -1);
    const fieldValidationErrors = [];
    const validatorContext = {
      addValidationErrors(errors) {
        errors.forEach((error) => fieldValidationErrors.push(error));
      },
      field(fName) {
        return getFieldInfo(fName);
      },
      genericKey: affectedKeyGeneric,
      isInArrayItemObject,
      isInSubObject,
      isModifier,
      isSet: (val !== undefined),
      key: affectedKey,
      obj,
      operator: op,
      parentField() {
        return getFieldInfo(fieldParentName);
      },
      siblingField(fName) {
        return getFieldInfo(fieldParentNameWithEndDot + fName);
      },
      validationContext,
      value: val,
      valueShouldBeChecked: (
        op !== '$unset' && op !== '$rename'
        && ((val !== undefined && val !== null) || (affectedKeyGeneric.slice(-2) === '.$' && val === null && !def.optional))
      ),
      ...(extendedCustomContext || {}),
    };
    const builtInValidators = [
      requiredValidator,
      typeValidator,
      allowedValuesValidator,
    ];
    const validators = builtInValidators
      .concat(schema._validators)
      .concat(SimpleSchema._validators);
    const fieldIsValid = def.type.some((typeDef) => {
      if (typeDef === SimpleSchema.Any) return true;
      const { type, ...definitionWithoutType } = def; 
      const finalValidatorContext = {
        ...validatorContext,
        definition: {
          ...definitionWithoutType,
          ...typeDef,
        },
      };
      const fieldValidators = validators.slice(0);
      if (typeof typeDef.custom === 'function') {
        fieldValidators.splice(builtInValidators.length, 0, typeDef.custom);
      }
      return fieldValidators.every((validator) => {
        const result = validator.call(finalValidatorContext);
        if (typeof result === 'string') {
          fieldValidationErrors.push({
            name: affectedKey,
            type: result,
            value: val,
          });
          return false;
        }
        if (typeof result === 'object' && result !== null) {
          fieldValidationErrors.push({
            name: affectedKey,
            value: val,
            ...result,
          });
          return false;
        }
        if (result === false) return false;
        return true;
      });
    });
    if (!fieldIsValid) {
      validationErrors = validationErrors.concat(fieldValidationErrors);
    }
  }
function validate ( val , affectedKey , affectedKeyGeneric , def , op , isInArrayItemObject , isInSubObject ) { if ( ! def ) { if ( op === '$unset' || ( op === '$currentDate' && affectedKey . endsWith ( '.$type' ) ) ) return ; validationErrors . push ( { name : affectedKey , type : SimpleSchema . ErrorTypes . KEY_NOT_IN_SCHEMA , value : val , } ) ; return ; } if ( op === '$rename' && ! schema . allowsKey ( val ) ) { validationErrors . push ( { name : val , type : SimpleSchema . ErrorTypes . KEY_NOT_IN_SCHEMA , value : null , } ) ; return ; } const fieldParentNameWithEndDot = getParentOfKey ( affectedKey , true ) ; const fieldParentName = fieldParentNameWithEndDot . slice ( 0 , - 1 ) ; const fieldValidationErrors = [ ] ; const validatorContext = { addValidationErrors ( errors ) { errors . forEach ( ( error ) => fieldValidationErrors . push ( error ) ) ; } , field ( fName ) { return getFieldInfo ( fName ) ; } , genericKey : affectedKeyGeneric , isInArrayItemObject , isInSubObject , isModifier , isSet : ( val !== undefined ) , key : affectedKey , obj , operator : op , parentField ( ) { return getFieldInfo ( fieldParentName ) ; } , siblingField ( fName ) { return getFieldInfo ( fieldParentNameWithEndDot + fName ) ; } , validationContext , value : val , valueShouldBeChecked : ( op !== '$unset' && op !== '$rename' && ( ( val !== undefined && val !== null ) || ( affectedKeyGeneric . slice ( - 2 ) === '.$' && val === null && ! def . optional ) ) ) , ... ( extendedCustomContext || { } ) , } ; const builtInValidators = [ requiredValidator , typeValidator , allowedValuesValidator , ] ; const validators = builtInValidators . concat ( schema . _validators ) . concat ( SimpleSchema . _validators ) ; const fieldIsValid = def . type . some ( ( typeDef ) => { if ( typeDef === SimpleSchema . Any ) return true ; const { type , ... definitionWithoutType } = def ; const finalValidatorContext = { ... validatorContext , definition : { ... definitionWithoutType , ... typeDef , } , } ; const fieldValidators = validators . slice ( 0 ) ; if ( typeof typeDef . custom === 'function' ) { fieldValidators . splice ( builtInValidators . length , 0 , typeDef . custom ) ; } return fieldValidators . every ( ( validator ) => { const result = validator . call ( finalValidatorContext ) ; if ( typeof result === 'string' ) { fieldValidationErrors . push ( { name : affectedKey , type : result , value : val , } ) ; return false ; } if ( typeof result === 'object' && result !== null ) { fieldValidationErrors . push ( { name : affectedKey , value : val , ... result , } ) ; return false ; } if ( result === false ) return false ; return true ; } ) ; } ) ; if ( ! fieldIsValid ) { validationErrors = validationErrors . concat ( fieldValidationErrors ) ; } }
Validation function called for each affected key
Validation function called for each affected key
// Get the schema for this key, marking invalid if there isn't one. // We don't need KEY_NOT_IN_SCHEMA error for $unset and we also don't need to continue // For $rename, make sure that the new name is allowed by the schema // Prepare the context object for the validator functions // Value checks are not necessary for null or undefined values, except // for non-optional null array items, or for $unset or $rename values // Loop through each of the definitions in the SimpleSchemaGroup. // If any return true, we're valid. // If the type is SimpleSchema.Any, then it is valid: // eslint-disable-line no-unused-vars // Take outer definition props like "optional" and "label" // and add them to inner props like "type" and "min" // Add custom field validators to the list after the built-in // validators but before the schema and global validators. // We use _.every just so that we don't continue running more validator // functions after the first one returns false or an error string. // If the validator returns a string, assume it is the // error type. // If the validator returns an object, assume it is an // error object. // If the validator returns false, assume they already // called this.addValidationErrors within the function // Any other return value we assume means it was valid