@availity/yup
Version:
Additional methods for yup validation library
352 lines (345 loc) • 10.8 kB
JavaScript
// src/index.ts
import { addMethod, array, number, object, string } from "yup";
// src/isRequired.ts
function isRequired(isRequired2 = true, msg) {
return this.test({
name: "isRequired",
exclusive: true,
message: msg || "This field is required.",
test(value) {
if (isRequired2) {
if (this.schema.type === "array") {
return Array.isArray(value) ? value.length > 0 : value !== void 0;
}
if (this.schema.type === "string") {
return value !== void 0 && value !== "";
}
return value !== void 0;
}
return true;
}
});
}
var isRequired_default = isRequired;
// src/npi.ts
var INTEGER_REGEX = /^\d*$/;
function npi(msg) {
return this.test({
name: "npi",
exclusive: true,
message: msg || "This field is invalid.",
test(value) {
if (!value) return true;
value += "";
if (!INTEGER_REGEX.test(value) || value.length !== 10) {
return false;
}
const firstDigit = value.charAt(0);
if (["1", "2", "3", "4"].indexOf(firstDigit) < 0) {
return false;
}
const digit = Number.parseInt(value.charAt(9), 10);
value = value.substring(0, 9);
value = `80840${value}`;
let alternate = true;
let total = 0;
for (let i = value.length; i > 0; i--) {
let next = Number.parseInt(value.charAt(i - 1), 10);
if (alternate) {
next *= 2;
if (next > 9) {
next = next % 10 + 1;
}
}
total += next;
alternate = !alternate;
}
const roundUp = Math.ceil(total / 10) * 10;
const calculatedCheck = roundUp - total;
return calculatedCheck === digit;
}
});
}
var npi_default = npi;
// src/phone.ts
var NANP_REGEXP = /^(\+?1[\s.-]?)?\(?[2-9]\d{2}[\s).-]?\s?[2-9]\d{2}[\s.-]?\d{4}$/;
function phone(msg) {
return this.test({
name: "phone",
exclusive: true,
message: msg || "This field is invalid",
test(value) {
if (!value) return true;
return NANP_REGEXP.test(value);
}
});
}
var phone_default = phone;
// src/date.ts
import { MixedSchema } from "yup";
import moment from "moment";
var defaultFormats = ["YYYY-MM-DD", "YYYYMMDD", "MMDDYYYY", "MM-DD-YYYY", "MM/DD/YYYY"];
var MomentDateSchema = class extends MixedSchema {
constructor({ format = [], typeError = "The date entered is in an invalid format." } = {}) {
super({ type: "avDate" });
const formats2 = Array.isArray(format) ? format : [format];
this._validFormats = [...defaultFormats, ...formats2];
this.withMutation((schema) => {
schema.typeError(typeError);
schema.transform(function transform(value, originalValue) {
if (value && this.isType(value)) {
return value;
}
return moment(originalValue, schema._validFormats, true);
});
});
}
// Check if the date is a valid moment object or an empty string
_typeCheck(value) {
return moment.isMoment(value) && (value.isValid() || value._i === "");
}
/**
* Validate if the date is on or after a specified min
*/
min(min, message) {
return this.test({
message: ({ min: minDate }) => message || `Date must be ${minDate} or later.`,
name: "min",
exclusive: true,
params: { min },
test(value) {
if (!min || !value || !value.isValid()) {
return true;
}
return value.isSameOrAfter(min);
}
});
}
/**
* Validate if the date is on or before a specified max
*/
max(max, message) {
return this.test({
message: ({ max: maxDate }) => message || `Date must be ${maxDate} or earlier.`,
name: "max",
exclusive: true,
params: { max },
test(value) {
if (!max || !value || !value.isValid()) {
return true;
}
return value.isSameOrBefore(max);
}
});
}
/**
* Validate if the date is between a specified min or max
*
* For Inlcusivity: `[]` === include & `()` === exclude
*/
between(min, max, message, inclusivity = "()") {
return this.test({
name: "between",
exclusive: true,
message: ({ min: minDate, max: maxDate }) => message || `Date must be between ${minDate} and ${maxDate}.`,
params: { min, max },
test(value) {
if (!value || !value.isValid() || !min || !max) {
return true;
}
return value.isBetween(min, max, void 0, inclusivity);
}
});
}
/**
* Set if the field is required and add a custom message
*/
isRequired(isRequired2 = true, message) {
return this.test({
name: "isRequired",
exclusive: true,
message: message || "This field is required.",
test(value) {
if (!isRequired2) {
return true;
}
return value ? !!value._i : false;
}
});
}
};
var avDate = (options) => new MomentDateSchema(options);
// src/dateRange.ts
import { MixedSchema as MixedSchema2, ValidationError } from "yup";
import moment2 from "moment";
import get from "lodash/get";
import merge from "lodash/merge";
var defaultOptions = {
startKey: "startDate",
endKey: "endDate",
format: "MM/DD/YYYY"
};
var formats = ["YYYY-MM-DD", "YYYYMMDD", "MMDDYYYY", "MM-DD-YYYY", "MM/DD/YYYY"];
var DateRangeSchema = class extends MixedSchema2 {
constructor(options) {
super({
type: "dateRange"
});
const { startKey, endKey, format } = merge({}, defaultOptions, options);
this.startKey = startKey;
this.endKey = endKey;
this.format = format;
this.withMutation((schema) => {
schema.transform(function mutate(value) {
const start = get(value, startKey);
const end = get(value, endKey);
return {
startDate: start ? schema.getValidDate(start) : start,
endDate: end ? schema.getValidDate(end) : end,
supportedFormats: [schema.format, ...formats]
};
});
});
}
/**
* Convert the string to a moment object
*/
getValidDate(value) {
return moment2(value, [this.format, ...formats], true);
}
/**
* Validate based on min and max distance between dates
*/
distance({
min: { value: minValue, units: minUnits = "day", errorMessage: minErrorMessage } = { value: 0 },
max: { value: maxValue, units: maxUnits = "day", errorMessage: maxErrorMessage } = { value: 0 }
} = {}) {
return this.test({
name: "distance",
exclusive: true,
test({ endDate, startDate } = {}) {
if (!minValue && !maxValue || !startDate || !endDate) return true;
if (maxValue && endDate.isAfter(startDate.add(maxValue, maxUnits), "day")) {
return new ValidationError(
maxErrorMessage || `The end date must be within ${maxValue} ${maxUnits}${maxValue > 1 ? "s" : ""} of the start date`,
{
startDate,
endDate
},
this.path
);
}
if (minValue && endDate.isBefore(startDate.add(minValue, minUnits), "day")) {
return new ValidationError(
minErrorMessage || `The end date must be greater than ${minValue} ${minUnits}${minValue > 1 ? "s" : ""} of the start date`,
{ startDate, endDate },
this.path
);
}
return true;
}
});
}
/**
* Validate start date is after given min
*/
min(min, message) {
return this.test({
message: message || (({ min: min2 }) => `Date Range must start on or after ${min2}`),
name: "min",
exclusive: true,
params: { min },
test({ startDate, supportedFormats } = {}) {
if (!startDate || !min) return true;
const minDate = moment2(min, supportedFormats, true);
return minDate.isValid() && minDate.isSameOrBefore(startDate);
}
});
}
/**
* Validate end date is before given max
*/
max(max, message) {
return this.test({
message: message || (({ max: max2 }) => `Date Range must end on or before ${max2}`),
name: "max",
exclusive: true,
params: { max },
test({ endDate, supportedFormats } = {}) {
if (!endDate || !max) return true;
const maxDate = moment2(max, supportedFormats, true);
return maxDate.isValid() && maxDate.isSameOrAfter(endDate);
}
});
}
/**
* Validate dates are between the set min and max
*/
between(min, max, message) {
return this.test({
message: message || (({ min: min2, max: max2 }) => `Date Range must be between ${min2} and ${max2}`),
name: "between",
exclusive: true,
params: { min, max },
test({ startDate, endDate, supportedFormats } = {}) {
if (!startDate || !endDate || !min || !max) return true;
const minDate = moment2(min, supportedFormats, true);
const maxDate = moment2(max, supportedFormats, true);
return maxDate.isValid() && minDate.isValid() && maxDate.isSameOrAfter(endDate) && minDate.isSameOrBefore(startDate);
}
});
}
/**
* Set the field to be required or not
*/
isRequired(isRequired2 = true, msg) {
return this.test({
name: "isRequired",
exclusive: true,
message: msg || "This field is required.",
test({ startDate, endDate } = {}) {
return !isRequired2 || !!(startDate && endDate);
}
});
}
typeError({ message }) {
return this.test({
name: "typeError",
exclusive: true,
test({ startDate, endDate } = {}) {
const errors = [];
if ((!startDate || !endDate) && (startDate || endDate)) {
errors.push(message || "Start and End Date are required.");
}
if (startDate && endDate && !startDate.isSameOrBefore(endDate)) {
errors.push("Start date must come before end date.");
}
if (startDate && !startDate.isValid()) {
errors.push("Start Date is invalid.");
}
if (endDate && !endDate.isValid()) {
errors.push("End Date is invalid.");
}
return errors.length > 0 ? new ValidationError(errors, { startDate, endDate }, this.path) : true;
}
});
}
_typeCheck(range = {}) {
const { startDate, endDate } = range;
return !!startDate && !!endDate && startDate.isValid() && endDate.isValid();
}
};
var dateRange = (opts) => new DateRangeSchema(opts);
// src/index.ts
addMethod(array, "isRequired", isRequired_default);
addMethod(number, "isRequired", isRequired_default);
addMethod(object, "isRequired", isRequired_default);
addMethod(string, "isRequired", isRequired_default);
addMethod(number, "npi", npi_default);
addMethod(string, "npi", npi_default);
addMethod(number, "phone", phone_default);
addMethod(string, "phone", phone_default);
export {
avDate,
dateRange
};