Fluentvalidation Ts Versions Save

A TypeScript-first library for building strongly-typed validation rules

v2.1.2

4 years ago

Fixes some typos and broken formatting in the README file.

v2.1.1

4 years ago

Fixes type inference for the new and improved .must rule.

For some reason TypeScript is unable to properly infer the type of arguments passed to the .must rule since the new functionality was added. This release changes the types under the hood to be explicit rather than aliased, which seems to fix the problem.

v2.1.0

4 years ago

This release includes a few bug fixes and small improvements, but also brings in some very useful extensions for the .must rule which make it a lot easier to define custom validation rules and associate custom error messages with them.

Summary

  • Updated dev dependencies
  • Bug fixes and improvements for the .scalePrecision rule
  • Enhanced capability of the .must rule to make it easier to configure reusable custom rules

Updated dev dependencies

All development dependencies have been updated to the latest version.

Bug fixes and improvements for .scalePrecision

  • Fixed an issue whereby the validation logic was incorrect for negative numbers
  • Improved the implementation under the hood to be more stable
  • Added a warning to the documentation regarding floating point arithmetic

New features for .must

This is the big change in this release, which makes it a lot more convenient to define custom validation logic that can be reused across several validators.

Previously it was possible to create reusable validation logic by defining named predicate functions:

// v2.0.0 and below

// Define some custom validation logic:
export const beNumeric = (value: string) => !isNaN(Number(value));

// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
  .must(beNumeric);

This is great, but in order to specify a custom error message we are forced to make a call to .withMessage as well:

// v2.0.0 and below

// Define some custom validation logic:
export const beNumeric = (value: string) => !isNaN(Number(value));
export const beNumericErrorMessage = 'Please enter a number';

// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
  .must(beNumeric)
  .withMessage(beNumericErrorMessage);

This works, but it feels clunky. Ideally we'd have a way of wrapping up both the validation logic and the error message into a single named variable.

Well, v2.1.0 brings exactly that:

// v2.1.0 and above

// Define some custom validation logic:
export const beNumeric = {
  predicate: (value: string) => !isNaN(Number(value)),
  message: 'Please enter a number',
};

// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
  .must(beNumeric);

Not only that, but you can also compose multiple custom rules together into arrays of rules which .must will accept:

// v2.1.0 and above

// Define some custom validation logic:
export const beNumeric = {
  predicate: (value: string) => !isNaN(Number(value)),
  message: 'Please enter a number',
};
export const beAnInteger = {
  predicate: (value: string) => Number(value) % 1 ===0,
  message: 'Please enter a whole number',
};
export const bePositive = {
  predicate: (value: string) => Number(value) > 0,
  message: 'Please enter a positive number',
};
export const bePositiveInteger = [beNumeric, beAnInteger, bePositive];

// Then, in the constructor of a validator:
this.ruleFor('stringProperty')
  .must(bePositiveInteger);

As you can see, these additions to the API of the .must rule open up a ton of new possibilities when it comes to defining custom validation rules. The examples here have only touched on these possibilities - see the README for more details.

v2.0.0

4 years ago

This release overhauls the target type of TModel in rules and conditions that are part of a .ruleForEach rule chain.

Previously the parameter of type TModel in such rule/condition definitions referred to the array property itself, but this was not of much use and went against the intuitive expectation that it would refer to the base model. As a result, the parameter of type TModel is now the base model itself, as opposed to the array property.

More specifically, this change affects the following rules and conditions:

  • .must
  • .setValidator
  • .when
  • .unless

💥 Breaking changes

Note that this is a breaking change as any rules/conditions defined within a .ruleForEach rule chain which make use of the TModel parameter will need to be modified. See the examples below for some guidance on how to migrate existing code.

Previous behaviour

An example based on the old behaviour might look something like this:

import { Validator } from 'fluentvalidation-ts';

type ExampleModel = {
  arrayProperty: Array<number>;
};

class ExampleValidator extends Validator<ExampleModel> {
  constructor() {
    super();

    this.ruleForEach('arrayProperty')
      .must((item, array) => item.displayIndex < array.length);
  }
}

As you can see, the second argument to the .must rule is the value of arrayProperty, rather than the value of the entire model.

New behaviour

An example based on the new behaviour might look something like this:

import { Validator } from 'fluentvalidation-ts';

type ExampleModel = {
  arrayProperty: Array<number>;
};

class ExampleValidator extends Validator<ExampleModel> {
  constructor() {
    super();

    this.ruleForEach('arrayProperty')
      .must((item, model) => item.displayIndex < model.arrayProperty.length);
  }
}

As you can see, the second argument to the .must rule is now the value of the entire model, but we can easily drill down into the array property if we need to.

v1.2.2

4 years ago

Fixes an oversight in the previous commit whereby types for the setValidator rule had not been updated in all relevant places.

v1.2.1

4 years ago

Updates the validatorProducer argument of the setValidator rule so that it can optionally take the base model being validated.

This change allows nested validators to depend on the state of the base model, by accepting the base model as a constructor argument.

Example:

this.ruleFor('nestedProperty')
  .setValidator(baseModel => new NestedValidator(baseModel));

v1.2.0

4 years ago

Changes the type of ValueValidationResult for array values, so that it is an array of validation results for the child elements, rather than an object containing validation results for the child elements keyed by their index in the array.

This change is needed to support Formik Field Arrays.

Previously:

myValidator.validate(modelWithArrayProperty);
// { arrayProperty: { 2: 'This element is invalid' } }

Now:

myValidator.validate(modelWithArrayProperty);
// { arrayProperty: [null, null, 'This element is invalid', null] }

Note: This change may break code that relies on the validation result for an array property being an object.

v1.1.0

4 years ago

Use TSdx for bundling and general configuration.

v1.0.3

4 years ago
  • Upgraded packages to address security issue
  • Updated README to correct typo
  • Recompiled code with updated line endings

v1.0.2

4 years ago

Includes further tweaks to the README file, and addresses an issue where changes to the dist folder had not been fully checked in.