Files
headroom/frontend/node_modules/@vinejs/vine/build/chunk-FED7BU4B.js
Santhosh Janardhanan de2d83092e feat: Reinitialize frontend with SvelteKit and TypeScript
- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
2026-02-17 16:19:59 -05:00

3144 lines
83 KiB
JavaScript

import {
SimpleErrorReporter,
SimpleMessagesProvider,
ValidationError,
helpers
} from "./chunk-YXNUTVGP.js";
import {
fields,
messages
} from "./chunk-M2DOTJGC.js";
import {
__export
} from "./chunk-MLKGABMK.js";
// src/vine/create_rule.ts
function createRule(validator, metaData) {
const rule = {
validator,
isAsync: metaData?.isAsync || validator.constructor.name === "AsyncFunction",
implicit: metaData?.implicit ?? false
};
return function(...options) {
return {
rule,
options: options[0]
};
};
}
// src/schema/builder.ts
import Macroable3 from "@poppinss/macroable";
// src/schema/base/literal.ts
import camelcase from "camelcase";
import Macroable from "@poppinss/macroable";
// src/symbols.ts
var symbols_exports = {};
__export(symbols_exports, {
COTYPE: () => COTYPE,
IS_OF_TYPE: () => IS_OF_TYPE,
ITYPE: () => ITYPE,
OTYPE: () => OTYPE,
PARSE: () => PARSE,
SUBTYPE: () => SUBTYPE,
UNIQUE_NAME: () => UNIQUE_NAME,
VALIDATION: () => VALIDATION
});
var UNIQUE_NAME = Symbol.for("schema_name");
var IS_OF_TYPE = Symbol.for("is_of_type");
var PARSE = Symbol.for("parse");
var ITYPE = Symbol.for("opaque_input_type");
var OTYPE = Symbol.for("opaque_type");
var COTYPE = Symbol.for("camelcase_opaque_type");
var VALIDATION = Symbol.for("to_validation");
var SUBTYPE = Symbol.for("subtype");
// src/schema/base/rules.ts
var requiredWhen = createRule(
(_, checker, field) => {
const shouldBeRequired = checker(field);
if (!field.isDefined && shouldBeRequired) {
field.report(messages.required, "required", field);
}
},
{
implicit: true
}
);
// src/schema/base/literal.ts
var BaseModifiersType = class extends Macroable {
/**
* Mark the field under validation as optional. An optional
* field allows both null and undefined values.
*/
optional(validations) {
return new OptionalModifier(this, validations);
}
/**
* Mark the field under validation to be null. The null value will
* be written to the output as well.
*
* If `optional` and `nullable` are used together, then both undefined
* and null values will be allowed.
*/
nullable() {
return new NullableModifier(this);
}
/**
* Apply transform on the final validated value. The transform method may
* convert the value to any new datatype.
*/
transform(transformer) {
return new TransformModifier(transformer, this);
}
};
var NullableModifier = class _NullableModifier extends BaseModifiersType {
#parent;
constructor(parent) {
super();
this.#parent = parent;
}
/**
* Creates a fresh instance of the underlying schema type
* and wraps it inside the nullable modifier
*/
clone() {
return new _NullableModifier(this.#parent.clone());
}
/**
* Compiles to compiler node
*/
[PARSE](propertyName, refs, options) {
const output = this.#parent[PARSE](propertyName, refs, options);
output.allowNull = true;
return output;
}
};
var OptionalModifier = class _OptionalModifier extends BaseModifiersType {
#parent;
/**
* Optional modifier validations list
*/
validations;
constructor(parent, validations) {
super();
this.#parent = parent;
this.validations = validations || [];
}
/**
* Shallow clones the validations. Since, there are no API's to mutate
* the validation options, we can safely copy them by reference.
*/
cloneValidations() {
return this.validations.map((validation) => {
return {
options: validation.options,
rule: validation.rule
};
});
}
/**
* Compiles validations
*/
compileValidations(refs) {
return this.validations.map((validation) => {
return {
ruleFnId: refs.track({
validator: validation.rule.validator,
options: validation.options
}),
implicit: validation.rule.implicit,
isAsync: validation.rule.isAsync
};
});
}
/**
* Push a validation to the validations chain.
*/
use(validation) {
this.validations.push(VALIDATION in validation ? validation[VALIDATION]() : validation);
return this;
}
requiredWhen(otherField, operator, expectedValue) {
if (typeof otherField === "function") {
return this.use(requiredWhen(otherField));
}
let checker;
switch (operator) {
case "=":
checker = (value) => value === expectedValue;
break;
case "!=":
checker = (value) => value !== expectedValue;
break;
case "in":
checker = (value) => expectedValue.includes(value);
break;
case "notIn":
checker = (value) => !expectedValue.includes(value);
break;
case ">":
checker = (value) => value > expectedValue;
break;
case "<":
checker = (value) => value < expectedValue;
break;
case ">=":
checker = (value) => value >= expectedValue;
break;
case "<=":
checker = (value) => value <= expectedValue;
}
return this.use(
requiredWhen((field) => {
const otherFieldValue = helpers.getNestedValue(otherField, field);
return checker(otherFieldValue);
})
);
}
/**
* Mark the field under validation as required when all
* the other fields are present with value other
* than `undefined` or `null`.
*/
requiredIfExists(fields2) {
const fieldsToExist = Array.isArray(fields2) ? fields2 : [fields2];
return this.use(
requiredWhen((field) => {
return fieldsToExist.every(
(otherField) => helpers.exists(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Mark the field under validation as required when any
* one of the other fields are present with non-nullable
* value.
*/
requiredIfAnyExists(fields2) {
return this.use(
requiredWhen((field) => {
return fields2.some(
(otherField) => helpers.exists(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Mark the field under validation as required when all
* the other fields are missing or their value is
* `undefined` or `null`.
*/
requiredIfMissing(fields2) {
const fieldsToExist = Array.isArray(fields2) ? fields2 : [fields2];
return this.use(
requiredWhen((field) => {
return fieldsToExist.every(
(otherField) => helpers.isMissing(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Mark the field under validation as required when any
* one of the other fields are missing.
*/
requiredIfAnyMissing(fields2) {
return this.use(
requiredWhen((field) => {
return fields2.some(
(otherField) => helpers.isMissing(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Creates a fresh instance of the underlying schema type
* and wraps it inside the optional modifier
*/
clone() {
return new _OptionalModifier(this.#parent.clone(), this.cloneValidations());
}
/**
* Compiles to compiler node
*/
[PARSE](propertyName, refs, options) {
const output = this.#parent[PARSE](propertyName, refs, options);
output.isOptional = true;
output.validations = output.validations.concat(this.compileValidations(refs));
return output;
}
};
var TransformModifier = class _TransformModifier extends BaseModifiersType {
#parent;
#transform;
constructor(transform, parent) {
super();
this.#transform = transform;
this.#parent = parent;
}
/**
* Creates a fresh instance of the underlying schema type
* and wraps it inside the transform modifier.
*/
clone() {
return new _TransformModifier(this.#transform, this.#parent.clone());
}
/**
* Compiles to compiler node
*/
[PARSE](propertyName, refs, options) {
const output = this.#parent[PARSE](propertyName, refs, options);
output.transformFnId = refs.trackTransformer(this.#transform);
return output;
}
};
var BaseLiteralType = class extends BaseModifiersType {
/**
* Field options
*/
options;
/**
* Set of validations to run
*/
validations;
constructor(options, validations) {
super();
this.options = {
bail: true,
allowNull: false,
isOptional: false,
...options
};
this.validations = validations || [];
}
/**
* Shallow clones the validations. Since, there are no API's to mutate
* the validation options, we can safely copy them by reference.
*/
cloneValidations() {
return this.validations.map((validation) => {
return {
options: validation.options,
rule: validation.rule
};
});
}
/**
* Shallow clones the options
*/
cloneOptions() {
return { ...this.options };
}
/**
* Compiles validations
*/
compileValidations(refs) {
return this.validations.map((validation) => {
return {
ruleFnId: refs.track({
validator: validation.rule.validator,
options: validation.options
}),
implicit: validation.rule.implicit,
isAsync: validation.rule.isAsync
};
});
}
/**
* Define a method to parse the input value. The method
* is invoked before any validation and hence you must
* perform type-checking to know the value you are
* working it.
*/
parse(callback) {
this.options.parse = callback;
return this;
}
/**
* Push a validation to the validations chain.
*/
use(validation) {
this.validations.push(VALIDATION in validation ? validation[VALIDATION]() : validation);
return this;
}
/**
* Enable/disable the bail mode. In bail mode, the field validations
* are stopped after the first error.
*/
bail(state) {
this.options.bail = state;
return this;
}
/**
* Compiles the schema type to a compiler node
*/
[PARSE](propertyName, refs, options) {
return {
type: "literal",
subtype: this[SUBTYPE],
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase(propertyName) : propertyName,
bail: this.options.bail,
allowNull: this.options.allowNull,
isOptional: this.options.isOptional,
parseFnId: this.options.parse ? refs.trackParser(this.options.parse) : void 0,
validations: this.compileValidations(refs)
};
}
};
// src/schema/any/main.ts
var VineAny = class _VineAny extends BaseLiteralType {
constructor(options, validations) {
super(options, validations);
}
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "any";
/**
* Clones the VineAny schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineAny(this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/enum/rules.ts
var enumRule = createRule((value, options, field) => {
const choices = typeof options.choices === "function" ? options.choices(field) : options.choices;
if (!choices.includes(value)) {
field.report(messages.enum, "enum", field, { choices });
}
});
// src/schema/enum/main.ts
var VineEnum = class _VineEnum extends BaseLiteralType {
/**
* Default collection of enum rules
*/
static rules = {
enum: enumRule
};
#values;
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "enum";
/**
* Returns the enum choices
*/
getChoices() {
return this.#values;
}
constructor(values, options, validations) {
super(options, validations || [enumRule({ choices: values })]);
this.#values = values;
}
/**
* Clones the VineEnum schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineEnum(this.#values, this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/date/main.ts
import dayjs2 from "dayjs";
// src/schema/date/rules.ts
import dayjs from "dayjs";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
import isSameOrBefore from "dayjs/plugin/isSameOrBefore.js";
import customParseFormat from "dayjs/plugin/customParseFormat.js";
var DEFAULT_DATE_FORMATS = ["YYYY-MM-DD", "YYYY-MM-DD HH:mm:ss"];
dayjs.extend(customParseFormat);
dayjs.extend(isSameOrAfter);
dayjs.extend(isSameOrBefore);
var dateRule = createRule((value, options, field) => {
if (typeof value !== "string" && typeof value !== "number") {
field.report(messages.date, "date", field);
return;
}
let isTimestampAllowed = false;
let isISOAllowed = false;
let formats = options.formats || DEFAULT_DATE_FORMATS;
if (Array.isArray(formats)) {
formats = [...formats];
isTimestampAllowed = formats.includes("x");
isISOAllowed = formats.includes("iso8601");
} else if (typeof formats !== "string") {
formats = { ...formats };
isTimestampAllowed = formats.format === "x";
isISOAllowed = formats.format === "iso";
}
const valueAsNumber = isTimestampAllowed ? helpers.asNumber(value) : value;
let dateTime;
if (isTimestampAllowed && !Number.isNaN(valueAsNumber)) {
dateTime = dayjs(valueAsNumber);
} else {
dateTime = dayjs(value, formats, true);
}
if (!dateTime.isValid() && isISOAllowed) {
dateTime = dayjs(value);
}
if (!dateTime.isValid()) {
field.report(messages.date, "date", field);
return;
}
field.meta.$value = dateTime;
field.meta.$formats = formats;
field.mutate(dateTime.toDate(), field);
});
var equalsRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const format = options.format || DEFAULT_DATE_FORMATS;
const dateTime = field.meta.$value;
const expectedValue = typeof options.expectedValue === "function" ? options.expectedValue(field) : options.expectedValue;
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
throw new Error(`Invalid datetime value "${expectedValue}" provided to the equals rule`);
}
if (!dateTime.isSame(expectedDateTime, compare)) {
field.report(messages["date.equals"], "date.equals", field, {
expectedValue,
compare
});
}
});
var afterRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const format = options.format || DEFAULT_DATE_FORMATS;
const dateTime = field.meta.$value;
const expectedValue = typeof options.expectedValue === "function" ? options.expectedValue(field) : options.expectedValue;
const expectedDateTime = expectedValue === "today" ? dayjs() : expectedValue === "tomorrow" ? dayjs().add(1, "day") : dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
throw new Error(`Invalid datetime value "${expectedValue}" provided to the after rule`);
}
if (!dateTime.isAfter(expectedDateTime, compare)) {
field.report(messages["date.after"], "date.after", field, {
expectedValue,
compare
});
}
});
var afterOrEqualRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const format = options.format || DEFAULT_DATE_FORMATS;
const dateTime = field.meta.$value;
const expectedValue = typeof options.expectedValue === "function" ? options.expectedValue(field) : options.expectedValue;
const expectedDateTime = expectedValue === "today" ? dayjs() : expectedValue === "tomorrow" ? dayjs().add(1, "day") : dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
throw new Error(`Invalid datetime value "${expectedValue}" provided to the afterOrEqual rule`);
}
if (!dateTime.isSameOrAfter(expectedDateTime, compare)) {
field.report(messages["date.afterOrEqual"], "date.afterOrEqual", field, {
expectedValue,
compare
});
}
});
var beforeRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const format = options.format || DEFAULT_DATE_FORMATS;
const dateTime = field.meta.$value;
const expectedValue = typeof options.expectedValue === "function" ? options.expectedValue(field) : options.expectedValue;
const expectedDateTime = expectedValue === "today" ? dayjs() : expectedValue === "yesterday" ? dayjs().subtract(1, "day") : dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
throw new Error(`Invalid datetime value "${expectedValue}" provided to the before rule`);
}
if (!dateTime.isBefore(expectedDateTime, compare)) {
field.report(messages["date.before"], "date.before", field, {
expectedValue,
compare
});
}
});
var beforeOrEqualRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const format = options.format || DEFAULT_DATE_FORMATS;
const dateTime = field.meta.$value;
const expectedValue = typeof options.expectedValue === "function" ? options.expectedValue(field) : options.expectedValue;
const expectedDateTime = expectedValue === "today" ? dayjs() : expectedValue === "yesterday" ? dayjs().subtract(1, "day") : dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
throw new Error(`Invalid datetime value "${expectedValue}" provided to the beforeOrEqual rule`);
}
if (!dateTime.isSameOrBefore(expectedDateTime, compare)) {
field.report(messages["date.beforeOrEqual"], "date.beforeOrEqual", field, {
expectedValue,
compare
});
}
});
var sameAsRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const dateTime = field.meta.$value;
const format = options.format || field.meta.$formats;
const expectedValue = helpers.getNestedValue(options.otherField, field);
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
return;
}
if (!dateTime.isSame(expectedDateTime, compare)) {
field.report(messages["date.sameAs"], "date.sameAs", field, {
otherField: options.otherField,
expectedValue,
compare
});
}
});
var notSameAsRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const dateTime = field.meta.$value;
const format = options.format || field.meta.$formats;
const expectedValue = helpers.getNestedValue(options.otherField, field);
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
return;
}
if (dateTime.isSame(expectedDateTime, compare)) {
field.report(messages["date.notSameAs"], "date.notSameAs", field, {
otherField: options.otherField,
expectedValue,
compare
});
}
});
var afterFieldRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const dateTime = field.meta.$value;
const format = options.format || field.meta.$formats;
const expectedValue = helpers.getNestedValue(options.otherField, field);
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
return;
}
if (!dateTime.isAfter(expectedDateTime, compare)) {
field.report(messages["date.afterField"], "date.afterField", field, {
otherField: options.otherField,
expectedValue,
compare
});
}
});
var afterOrSameAsRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const dateTime = field.meta.$value;
const format = options.format || field.meta.$formats;
const expectedValue = helpers.getNestedValue(options.otherField, field);
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
return;
}
if (!dateTime.isSameOrAfter(expectedDateTime, compare)) {
field.report(messages["date.afterOrSameAs"], "date.afterOrSameAs", field, {
otherField: options.otherField,
expectedValue,
compare
});
}
});
var beforeFieldRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const dateTime = field.meta.$value;
const format = options.format || field.meta.$formats;
const expectedValue = helpers.getNestedValue(options.otherField, field);
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
return;
}
if (!dateTime.isBefore(expectedDateTime, compare)) {
field.report(messages["date.beforeField"], "date.beforeField", field, {
otherField: options.otherField,
expectedValue,
compare
});
}
});
var beforeOrSameAsRule = createRule((_, options, field) => {
if (!field.meta.$value) {
return;
}
const compare = options.compare || "day";
const dateTime = field.meta.$value;
const format = options.format || field.meta.$formats;
const expectedValue = helpers.getNestedValue(options.otherField, field);
const expectedDateTime = dayjs(expectedValue, format, true);
if (!expectedDateTime.isValid()) {
return;
}
if (!dateTime.isSameOrBefore(expectedDateTime, compare)) {
field.report(messages["date.beforeOrSameAs"], "date.beforeOrSameAs", field, {
otherField: options.otherField,
expectedValue,
compare
});
}
});
var weekendRule = createRule((_, __, field) => {
if (!field.meta.$value) {
return;
}
const dateTime = field.meta.$value;
const day = dateTime.day();
if (day !== 0 && day !== 6) {
field.report(messages["date.weekend"], "date.weekend", field);
}
});
var weekdayRule = createRule((_, __, field) => {
if (!field.meta.$value) {
return;
}
const dateTime = field.meta.$value;
const day = dateTime.day();
if (day === 0 || day === 6) {
field.report(messages["date.weekday"], "date.weekday", field);
}
});
// src/schema/date/main.ts
var VineDate = class _VineDate extends BaseLiteralType {
/**
* Available VineDate rules
*/
static rules = {
equals: equalsRule,
after: afterRule,
afterOrEqual: afterOrEqualRule,
before: beforeRule,
beforeOrEqual: beforeOrEqualRule,
sameAs: sameAsRule,
notSameAs: notSameAsRule,
afterField: afterFieldRule,
afterOrSameAs: afterOrSameAsRule,
beforeField: beforeFieldRule,
beforeOrSameAs: beforeOrSameAsRule,
weekend: weekendRule,
weekday: weekdayRule
};
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.date";
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "date";
/**
* Checks if the value is of date type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
if (typeof value !== "string") {
return false;
}
return dayjs2(value, this.options.formats || DEFAULT_DATE_FORMATS, true).isValid();
};
constructor(options, validations) {
super(options, validations || [dateRule(options || {})]);
}
/**
* The equals rule compares the input value to be same
* as the expected value.
*
* By default, the comparions of day, month and years are performed.
*/
equals(expectedValue, options) {
return this.use(equalsRule({ expectedValue, ...options }));
}
/**
* The after rule compares the input value to be after
* the expected value.
*
* By default, the comparions of day, month and years are performed.
*/
after(expectedValue, options) {
return this.use(afterRule({ expectedValue, ...options }));
}
/**
* The after or equal rule compares the input value to be
* after or equal to the expected value.
*
* By default, the comparions of day, month and years are performed.
*/
afterOrEqual(expectedValue, options) {
return this.use(afterOrEqualRule({ expectedValue, ...options }));
}
/**
* The before rule compares the input value to be before
* the expected value.
*
* By default, the comparions of day, month and years are performed.
*/
before(expectedValue, options) {
return this.use(beforeRule({ expectedValue, ...options }));
}
/**
* The before rule compares the input value to be before
* the expected value.
*
* By default, the comparions of day, month and years are performed.
*/
beforeOrEqual(expectedValue, options) {
return this.use(beforeOrEqualRule({ expectedValue, ...options }));
}
/**
* The sameAs rule expects the input value to be same
* as the value of the other field.
*
* By default, the comparions of day, month and years are performed
*/
sameAs(otherField, options) {
return this.use(sameAsRule({ otherField, ...options }));
}
/**
* The notSameAs rule expects the input value to be different
* from the other field's value
*
* By default, the comparions of day, month and years are performed
*/
notSameAs(otherField, options) {
return this.use(notSameAsRule({ otherField, ...options }));
}
/**
* The afterField rule expects the input value to be after
* the other field's value.
*
* By default, the comparions of day, month and years are performed
*/
afterField(otherField, options) {
return this.use(afterFieldRule({ otherField, ...options }));
}
/**
* The afterOrSameAs rule expects the input value to be after
* or equal to the other field's value.
*
* By default, the comparions of day, month and years are performed
*/
afterOrSameAs(otherField, options) {
return this.use(afterOrSameAsRule({ otherField, ...options }));
}
/**
* The beforeField rule expects the input value to be before
* the other field's value.
*
* By default, the comparions of day, month and years are performed
*/
beforeField(otherField, options) {
return this.use(beforeFieldRule({ otherField, ...options }));
}
/**
* The beforeOrSameAs rule expects the input value to be before
* or same as the other field's value.
*
* By default, the comparions of day, month and years are performed
*/
beforeOrSameAs(otherField, options) {
return this.use(beforeOrSameAsRule({ otherField, ...options }));
}
/**
* The weekend rule ensures the date falls on a weekend
*/
weekend() {
return this.use(weekendRule());
}
/**
* The weekday rule ensures the date falls on a weekday
*/
weekday() {
return this.use(weekdayRule());
}
/**
* Clones the VineDate schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineDate(this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/union/main.ts
import camelcase2 from "camelcase";
var VineUnion = class _VineUnion {
#conditionals;
#otherwiseCallback = (_, field) => {
field.report(messages.union, "union", field);
};
constructor(conditionals) {
this.#conditionals = conditionals;
}
/**
* Define a fallback method to invoke when all of the union conditions
* fail. You may use this method to report an error.
*/
otherwise(callback) {
this.#otherwiseCallback = callback;
return this;
}
/**
* Clones the VineUnion schema type.
*/
clone() {
const cloned = new _VineUnion(this.#conditionals);
cloned.otherwise(this.#otherwiseCallback);
return cloned;
}
/**
* Compiles to a union
*/
[PARSE](propertyName, refs, options) {
return {
type: "union",
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase2(propertyName) : propertyName,
elseConditionalFnRefId: refs.trackConditional(this.#otherwiseCallback),
conditions: this.#conditionals.map(
(conditional) => conditional[PARSE](propertyName, refs, options)
)
};
}
};
// src/schema/union/conditional.ts
var UnionConditional = class {
/**
* Properties to merge when conditonal is true
*/
#schema;
/**
* Conditional to evaluate
*/
#conditional;
constructor(conditional, schema) {
this.#schema = schema;
this.#conditional = conditional;
}
/**
* Compiles to a union conditional
*/
[PARSE](propertyName, refs, options) {
return {
conditionalFnRefId: refs.trackConditional(this.#conditional),
schema: this.#schema[PARSE](propertyName, refs, options)
};
}
};
// src/schema/union/builder.ts
function union(conditionals) {
return new VineUnion(conditionals);
}
union.if = function unionIf(conditon, schema) {
return new UnionConditional(conditon, schema);
};
union.else = function unionElse(schema) {
return new UnionConditional(() => true, schema);
};
// src/schema/tuple/main.ts
import camelcase3 from "camelcase";
// src/schema/base/main.ts
import Macroable2 from "@poppinss/macroable";
var BaseModifiersType2 = class extends Macroable2 {
/**
* Mark the field under validation as optional. An optional
* field allows both null and undefined values.
*/
optional() {
return new OptionalModifier2(this);
}
/**
* Mark the field under validation to be null. The null value will
* be written to the output as well.
*
* If `optional` and `nullable` are used together, then both undefined
* and null values will be allowed.
*/
nullable() {
return new NullableModifier2(this);
}
};
var NullableModifier2 = class _NullableModifier extends BaseModifiersType2 {
#parent;
constructor(parent) {
super();
this.#parent = parent;
}
/**
* Creates a fresh instance of the underlying schema type
* and wraps it inside the nullable modifier
*/
clone() {
return new _NullableModifier(this.#parent.clone());
}
/**
* Compiles to compiler node
*/
[PARSE](propertyName, refs, options) {
const output = this.#parent[PARSE](propertyName, refs, options);
if (output.type !== "union") {
output.allowNull = true;
}
return output;
}
};
var OptionalModifier2 = class _OptionalModifier extends BaseModifiersType2 {
#parent;
/**
* Optional modifier validations list
*/
validations;
constructor(parent, validations) {
super();
this.#parent = parent;
this.validations = validations || [];
}
/**
* Shallow clones the validations. Since, there are no API's to mutate
* the validation options, we can safely copy them by reference.
*/
cloneValidations() {
return this.validations.map((validation) => {
return {
options: validation.options,
rule: validation.rule
};
});
}
/**
* Compiles validations
*/
compileValidations(refs) {
return this.validations.map((validation) => {
return {
ruleFnId: refs.track({
validator: validation.rule.validator,
options: validation.options
}),
implicit: validation.rule.implicit,
isAsync: validation.rule.isAsync
};
});
}
/**
* Push a validation to the validations chain.
*/
use(validation) {
this.validations.push(VALIDATION in validation ? validation[VALIDATION]() : validation);
return this;
}
requiredWhen(otherField, operator, expectedValue) {
if (typeof otherField === "function") {
return this.use(requiredWhen(otherField));
}
let checker;
switch (operator) {
case "=":
checker = (value) => value === expectedValue;
break;
case "!=":
checker = (value) => value !== expectedValue;
break;
case "in":
checker = (value) => expectedValue.includes(value);
break;
case "notIn":
checker = (value) => !expectedValue.includes(value);
break;
case ">":
checker = (value) => value > expectedValue;
break;
case "<":
checker = (value) => value < expectedValue;
break;
case ">=":
checker = (value) => value >= expectedValue;
break;
case "<=":
checker = (value) => value <= expectedValue;
}
return this.use(
requiredWhen((field) => {
const otherFieldValue = helpers.getNestedValue(otherField, field);
return checker(otherFieldValue);
})
);
}
/**
* Mark the field under validation as required when all
* the other fields are present with value other
* than `undefined` or `null`.
*/
requiredIfExists(fields2) {
const fieldsToExist = Array.isArray(fields2) ? fields2 : [fields2];
return this.use(
requiredWhen((field) => {
return fieldsToExist.every((otherField) => {
return helpers.exists(helpers.getNestedValue(otherField, field));
});
})
);
}
/**
* Mark the field under validation as required when any
* one of the other fields are present with non-nullable
* value.
*/
requiredIfAnyExists(fields2) {
return this.use(
requiredWhen((field) => {
return fields2.some(
(otherField) => helpers.exists(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Mark the field under validation as required when all
* the other fields are missing or their value is
* `undefined` or `null`.
*/
requiredIfMissing(fields2) {
const fieldsToExist = Array.isArray(fields2) ? fields2 : [fields2];
return this.use(
requiredWhen((field) => {
return fieldsToExist.every(
(otherField) => helpers.isMissing(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Mark the field under validation as required when any
* one of the other fields are missing.
*/
requiredIfAnyMissing(fields2) {
return this.use(
requiredWhen((field) => {
return fields2.some(
(otherField) => helpers.isMissing(helpers.getNestedValue(otherField, field))
);
})
);
}
/**
* Creates a fresh instance of the underlying schema type
* and wraps it inside the optional modifier
*/
clone() {
return new _OptionalModifier(this.#parent.clone(), this.cloneValidations());
}
/**
* Compiles to compiler node
*/
[PARSE](propertyName, refs, options) {
const output = this.#parent[PARSE](propertyName, refs, options);
if (output.type !== "union") {
output.isOptional = true;
output.validations = output.validations.concat(this.compileValidations(refs));
}
return output;
}
};
var BaseType = class extends BaseModifiersType2 {
/**
* Field options
*/
options;
/**
* Set of validations to run
*/
validations;
constructor(options, validations) {
super();
this.options = options || {
bail: true,
allowNull: false,
isOptional: false
};
this.validations = validations || [];
}
/**
* Shallow clones the validations. Since, there are no API's to mutate
* the validation options, we can safely copy them by reference.
*/
cloneValidations() {
return this.validations.map((validation) => {
return {
options: validation.options,
rule: validation.rule
};
});
}
/**
* Shallow clones the options
*/
cloneOptions() {
return { ...this.options };
}
/**
* Compiles validations
*/
compileValidations(refs) {
return this.validations.map((validation) => {
return {
ruleFnId: refs.track({
validator: validation.rule.validator,
options: validation.options
}),
implicit: validation.rule.implicit,
isAsync: validation.rule.isAsync
};
});
}
/**
* Define a method to parse the input value. The method
* is invoked before any validation and hence you must
* perform type-checking to know the value you are
* working it.
*/
parse(callback) {
this.options.parse = callback;
return this;
}
/**
* Push a validation to the validations chain.
*/
use(validation) {
this.validations.push(VALIDATION in validation ? validation[VALIDATION]() : validation);
return this;
}
/**
* Enable/disable the bail mode. In bail mode, the field validations
* are stopped after the first error.
*/
bail(state) {
this.options.bail = state;
return this;
}
};
// src/schema/tuple/main.ts
var VineTuple = class _VineTuple extends BaseType {
#schemas;
/**
* Whether or not to allow unknown properties
*/
#allowUnknownProperties = false;
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.array";
/**
* Checks if the value is of array type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
return Array.isArray(value);
};
constructor(schemas, options, validations) {
super(options, validations);
this.#schemas = schemas;
}
/**
* Copy unknown properties to the final output.
*/
allowUnknownProperties() {
this.#allowUnknownProperties = true;
return this;
}
/**
* Clone object
*/
clone() {
const cloned = new _VineTuple(
this.#schemas.map((schema) => schema.clone()),
this.cloneOptions(),
this.cloneValidations()
);
if (this.#allowUnknownProperties) {
cloned.allowUnknownProperties();
}
return cloned;
}
/**
* Compiles to array data type
*/
[PARSE](propertyName, refs, options) {
return {
type: "tuple",
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase3(propertyName) : propertyName,
bail: this.options.bail,
allowNull: this.options.allowNull,
isOptional: this.options.isOptional,
allowUnknownProperties: this.#allowUnknownProperties,
parseFnId: this.options.parse ? refs.trackParser(this.options.parse) : void 0,
validations: this.compileValidations(refs),
properties: this.#schemas.map((schema, index) => schema[PARSE](String(index), refs, options))
};
}
};
// src/schema/array/main.ts
import camelcase4 from "camelcase";
// src/schema/array/rules.ts
var minLengthRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value.length < options.min) {
field.report(messages["array.minLength"], "array.minLength", field, options);
}
});
var maxLengthRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value.length > options.max) {
field.report(messages["array.maxLength"], "array.maxLength", field, options);
}
});
var fixedLengthRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value.length !== options.size) {
field.report(messages["array.fixedLength"], "array.fixedLength", field, options);
}
});
var notEmptyRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (value.length <= 0) {
field.report(messages.notEmpty, "notEmpty", field);
}
});
var distinctRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isDistinct(value, options.fields)) {
field.report(messages.distinct, "distinct", field, options);
}
});
var compactRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
field.mutate(
value.filter((item) => helpers.exists(item) && item !== ""),
field
);
});
// src/schema/array/main.ts
var VineArray = class _VineArray extends BaseType {
/**
* Default collection of array rules
*/
static rules = {
compact: compactRule,
notEmpty: notEmptyRule,
distinct: distinctRule,
minLength: minLengthRule,
maxLength: maxLengthRule,
fixedLength: fixedLengthRule
};
#schema;
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.array";
/**
* Checks if the value is of array type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
return Array.isArray(value);
};
constructor(schema, options, validations) {
super(options, validations);
this.#schema = schema;
}
/**
* Enforce a minimum length on an array field
*/
minLength(expectedLength) {
return this.use(minLengthRule({ min: expectedLength }));
}
/**
* Enforce a maximum length on an array field
*/
maxLength(expectedLength) {
return this.use(maxLengthRule({ max: expectedLength }));
}
/**
* Enforce a fixed length on an array field
*/
fixedLength(expectedLength) {
return this.use(fixedLengthRule({ size: expectedLength }));
}
/**
* Ensure the array is not empty
*/
notEmpty() {
return this.use(notEmptyRule());
}
/**
* Ensure array elements are distinct/unique
*/
distinct(fields2) {
return this.use(distinctRule({ fields: fields2 }));
}
/**
* Removes empty strings, null and undefined values from the array
*/
compact() {
return this.use(compactRule());
}
/**
* Clones the VineArray schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineArray(this.#schema.clone(), this.cloneOptions(), this.cloneValidations());
}
/**
* Compiles to array data type
*/
[PARSE](propertyName, refs, options) {
return {
type: "array",
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase4(propertyName) : propertyName,
bail: this.options.bail,
allowNull: this.options.allowNull,
isOptional: this.options.isOptional,
each: this.#schema[PARSE]("*", refs, options),
parseFnId: this.options.parse ? refs.trackParser(this.options.parse) : void 0,
validations: this.compileValidations(refs)
};
}
};
// src/schema/object/main.ts
import camelcase5 from "camelcase";
var VineCamelCaseObject = class _VineCamelCaseObject extends BaseModifiersType2 {
#schema;
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "types.object";
/**
* Checks if the value is of object type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
return value !== null && typeof value === "object" && !Array.isArray(value);
};
constructor(schema) {
super();
this.#schema = schema;
}
/**
* Clone object
*/
clone() {
return new _VineCamelCaseObject(this.#schema.clone());
}
/**
* Compiles the schema type to a compiler node
*/
[PARSE](propertyName, refs, options) {
options.toCamelCase = true;
return this.#schema[PARSE](propertyName, refs, options);
}
};
var VineObject = class _VineObject extends BaseType {
/**
* Object properties
*/
#properties;
/**
* Object groups to merge based on conditionals
*/
#groups = [];
/**
* Whether or not to allow unknown properties
*/
#allowUnknownProperties = false;
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.object";
/**
* Checks if the value is of object type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
return value !== null && typeof value === "object" && !Array.isArray(value);
};
constructor(properties, options, validations) {
if (!properties) {
throw new Error(
'Missing properties for "vine.object". Use an empty object if you do not want to validate any specific fields'
);
}
super(options, validations);
this.#properties = properties;
}
/**
* Returns a clone copy of the object properties. The object groups
* are not copied to keep the implementations simple and easy to
* reason about.
*/
getProperties() {
return Object.keys(this.#properties).reduce((result, key) => {
result[key] = this.#properties[key].clone();
return result;
}, {});
}
/**
* Copy unknown properties to the final output.
*/
allowUnknownProperties() {
this.#allowUnknownProperties = true;
return this;
}
/**
* Merge a union to the object groups. The union can be a "vine.union"
* with objects, or a "vine.object.union" with properties.
*/
merge(group2) {
this.#groups.push(group2);
return this;
}
/**
* Clone object
*/
clone() {
const cloned = new _VineObject(
this.getProperties(),
this.cloneOptions(),
this.cloneValidations()
);
this.#groups.forEach((group2) => cloned.merge(group2));
if (this.#allowUnknownProperties) {
cloned.allowUnknownProperties();
}
return cloned;
}
/**
* Applies camelcase transform
*/
toCamelCase() {
return new VineCamelCaseObject(this);
}
/**
* Compiles the schema type to a compiler node
*/
[PARSE](propertyName, refs, options) {
return {
type: "object",
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase5(propertyName) : propertyName,
bail: this.options.bail,
allowNull: this.options.allowNull,
isOptional: this.options.isOptional,
parseFnId: this.options.parse ? refs.trackParser(this.options.parse) : void 0,
allowUnknownProperties: this.#allowUnknownProperties,
validations: this.compileValidations(refs),
properties: Object.keys(this.#properties).map((property) => {
return this.#properties[property][PARSE](property, refs, options);
}),
groups: this.#groups.map((group2) => {
return group2[PARSE](refs, options);
})
};
}
};
// src/schema/record/main.ts
import camelcase6 from "camelcase";
// src/schema/record/rules.ts
var minLengthRule2 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (Object.keys(value).length < options.min) {
field.report(messages["record.minLength"], "record.minLength", field, options);
}
});
var maxLengthRule2 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (Object.keys(value).length > options.max) {
field.report(messages["record.maxLength"], "record.maxLength", field, options);
}
});
var fixedLengthRule2 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (Object.keys(value).length !== options.size) {
field.report(messages["record.fixedLength"], "record.fixedLength", field, options);
}
});
var validateKeysRule = createRule(
(value, callback, field) => {
if (!field.isValid) {
return;
}
callback(Object.keys(value), field);
}
);
// src/schema/record/main.ts
var VineRecord = class _VineRecord extends BaseType {
/**
* Default collection of record rules
*/
static rules = {
maxLength: maxLengthRule2,
minLength: minLengthRule2,
fixedLength: fixedLengthRule2,
validateKeys: validateKeysRule
};
#schema;
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.object";
/**
* Checks if the value is of object type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
return value !== null && typeof value === "object" && !Array.isArray(value);
};
constructor(schema, options, validations) {
super(options, validations);
this.#schema = schema;
}
/**
* Enforce a minimum length on an object field
*/
minLength(expectedLength) {
return this.use(minLengthRule2({ min: expectedLength }));
}
/**
* Enforce a maximum length on an object field
*/
maxLength(expectedLength) {
return this.use(maxLengthRule2({ max: expectedLength }));
}
/**
* Enforce a fixed length on an object field
*/
fixedLength(expectedLength) {
return this.use(fixedLengthRule2({ size: expectedLength }));
}
/**
* Register a callback to validate the object keys
*/
validateKeys(...args) {
return this.use(validateKeysRule(...args));
}
/**
* Clones the VineRecord schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineRecord(
this.#schema.clone(),
this.cloneOptions(),
this.cloneValidations()
);
}
/**
* Compiles to record data type
*/
[PARSE](propertyName, refs, options) {
return {
type: "record",
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase6(propertyName) : propertyName,
bail: this.options.bail,
allowNull: this.options.allowNull,
isOptional: this.options.isOptional,
each: this.#schema[PARSE]("*", refs, options),
parseFnId: this.options.parse ? refs.trackParser(this.options.parse) : void 0,
validations: this.compileValidations(refs)
};
}
};
// src/schema/string/rules.ts
import camelcase7 from "camelcase";
import normalizeUrl from "normalize-url";
import escape from "validator/lib/escape.js";
import normalizeEmail from "validator/lib/normalizeEmail.js";
var stringRule = createRule((value, _, field) => {
if (typeof value !== "string") {
field.report(messages.string, "string", field);
}
});
var emailRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isEmail(value, options)) {
field.report(messages.email, "email", field);
}
});
var mobileRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
const normalizedOptions = options && typeof options === "function" ? options(field) : options;
const locales = normalizedOptions?.locale || "any";
if (!helpers.isMobilePhone(value, locales, normalizedOptions)) {
field.report(messages.mobile, "mobile", field);
}
});
var ipAddressRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isIP(value, options?.version)) {
field.report(messages.ipAddress, "ipAddress", field);
}
});
var regexRule = createRule((value, expression, field) => {
if (!field.isValid) {
return;
}
if (!expression.test(value)) {
field.report(messages.regex, "regex", field);
}
});
var hexCodeRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isHexColor(value)) {
field.report(messages.hexCode, "hexCode", field);
}
});
var urlRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isURL(value, options)) {
field.report(messages.url, "url", field);
}
});
var activeUrlRule = createRule(async (value, _, field) => {
if (!field.isValid) {
return;
}
if (!await helpers.isActiveURL(value)) {
field.report(messages.activeUrl, "activeUrl", field);
}
});
var alphaRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
let characterSet = "a-zA-Z";
if (options) {
if (options.allowSpaces) {
characterSet += "\\s";
}
if (options.allowDashes) {
characterSet += "-";
}
if (options.allowUnderscores) {
characterSet += "_";
}
}
const expression = new RegExp(`^[${characterSet}]+$`);
if (!expression.test(value)) {
field.report(messages.alpha, "alpha", field);
}
});
var alphaNumericRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
let characterSet = "a-zA-Z0-9";
if (options) {
if (options.allowSpaces) {
characterSet += "\\s";
}
if (options.allowDashes) {
characterSet += "-";
}
if (options.allowUnderscores) {
characterSet += "_";
}
}
const expression = new RegExp(`^[${characterSet}]+$`);
if (!expression.test(value)) {
field.report(messages.alphaNumeric, "alphaNumeric", field);
}
}
);
var minLengthRule3 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value.length < options.min) {
field.report(messages.minLength, "minLength", field, options);
}
});
var maxLengthRule3 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value.length > options.max) {
field.report(messages.maxLength, "maxLength", field, options);
}
});
var fixedLengthRule3 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value.length !== options.size) {
field.report(messages.fixedLength, "fixedLength", field, options);
}
});
var endsWithRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!value.endsWith(options.substring)) {
field.report(messages.endsWith, "endsWith", field, options);
}
});
var startsWithRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!value.startsWith(options.substring)) {
field.report(messages.startsWith, "startsWith", field, options);
}
});
var sameAsRule2 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
const input = helpers.getNestedValue(options.otherField, field);
if (input !== value) {
field.report(messages.sameAs, "sameAs", field, options);
return;
}
});
var notSameAsRule2 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
const input = helpers.getNestedValue(options.otherField, field);
if (input === value) {
field.report(messages.notSameAs, "notSameAs", field, options);
return;
}
});
var confirmedRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
const otherField = options?.confirmationField || `${field.name}_confirmation`;
const input = field.parent[otherField];
if (input !== value) {
field.report(messages.confirmed, "confirmed", field, { otherField });
return;
}
}
);
var trimRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
field.mutate(value.trim(), field);
});
var normalizeEmailRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
field.mutate(normalizeEmail.default(value, options), field);
}
);
var toUpperCaseRule = createRule(
(value, locales, field) => {
if (!field.isValid) {
return;
}
field.mutate(value.toLocaleUpperCase(locales), field);
}
);
var toLowerCaseRule = createRule(
(value, locales, field) => {
if (!field.isValid) {
return;
}
field.mutate(value.toLocaleLowerCase(locales), field);
}
);
var toCamelCaseRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
field.mutate(camelcase7(value), field);
});
var escapeRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
field.mutate(escape.default(value), field);
});
var normalizeUrlRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
field.mutate(normalizeUrl(value, options), field);
}
);
var inRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
const choices = typeof options.choices === "function" ? options.choices(field) : options.choices;
if (!choices.includes(value)) {
field.report(messages.in, "in", field, options);
return;
}
}
);
var notInRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
const list = typeof options.list === "function" ? options.list(field) : options.list;
if (list.includes(value)) {
field.report(messages.notIn, "notIn", field, options);
return;
}
}
);
var creditCardRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
const providers = options ? typeof options === "function" ? options(field)?.provider || [] : options.provider : [];
if (!providers.length) {
if (!helpers.isCreditCard(value)) {
field.report(messages.creditCard, "creditCard", field, {
providersList: "credit"
});
}
} else {
const matchesAnyProvider = providers.find(
(provider) => helpers.isCreditCard(value, { provider })
);
if (!matchesAnyProvider) {
field.report(messages.creditCard, "creditCard", field, {
providers,
providersList: providers.join("/")
});
}
}
});
var passportRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
const countryCodes = typeof options === "function" ? options(field).countryCode : options.countryCode;
const matchesAnyCountryCode = countryCodes.find(
(countryCode) => helpers.isPassportNumber(value, countryCode)
);
if (!matchesAnyCountryCode) {
field.report(messages.passport, "passport", field, { countryCodes });
}
});
var postalCodeRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
const countryCodes = options ? typeof options === "function" ? options(field)?.countryCode || [] : options.countryCode : [];
if (!countryCodes.length) {
if (!helpers.isPostalCode(value, "any")) {
field.report(messages.postalCode, "postalCode", field);
}
} else {
const matchesAnyCountryCode = countryCodes.find(
(countryCode) => helpers.isPostalCode(value, countryCode)
);
if (!matchesAnyCountryCode) {
field.report(messages.postalCode, "postalCode", field, { countryCodes });
}
}
});
var uuidRule = createRule(
(value, options, field) => {
if (!field.isValid) {
return;
}
if (!options || !options.version) {
if (!helpers.isUUID(value)) {
field.report(messages.uuid, "uuid", field);
}
} else {
const matchesAnyVersion = options.version.find(
(version) => helpers.isUUID(value, version)
);
if (!matchesAnyVersion) {
field.report(messages.uuid, "uuid", field, options);
}
}
}
);
var ulidRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isULID(value)) {
field.report(messages.ulid, "ulid", field);
}
});
var asciiRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isAscii(value)) {
field.report(messages.ascii, "ascii", field);
}
});
var ibanRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isIBAN(value)) {
field.report(messages.iban, "iban", field);
}
});
var jwtRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isJWT(value)) {
field.report(messages.jwt, "jwt", field);
}
});
var coordinatesRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isLatLong(value)) {
field.report(messages.coordinates, "coordinates", field);
}
});
// src/schema/string/main.ts
var VineString = class _VineString extends BaseLiteralType {
static rules = {
in: inRule,
jwt: jwtRule,
url: urlRule,
iban: ibanRule,
uuid: uuidRule,
ulid: ulidRule,
trim: trimRule,
email: emailRule,
alpha: alphaRule,
ascii: asciiRule,
notIn: notInRule,
regex: regexRule,
escape: escapeRule,
sameAs: sameAsRule2,
mobile: mobileRule,
string: stringRule,
hexCode: hexCodeRule,
passport: passportRule,
endsWith: endsWithRule,
confirmed: confirmedRule,
activeUrl: activeUrlRule,
minLength: minLengthRule3,
notSameAs: notSameAsRule2,
maxLength: maxLengthRule3,
ipAddress: ipAddressRule,
creditCard: creditCardRule,
postalCode: postalCodeRule,
startsWith: startsWithRule,
toUpperCase: toUpperCaseRule,
toLowerCase: toLowerCaseRule,
toCamelCase: toCamelCaseRule,
fixedLength: fixedLengthRule3,
coordinates: coordinatesRule,
normalizeUrl: normalizeUrlRule,
alphaNumeric: alphaNumericRule,
normalizeEmail: normalizeEmailRule
};
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "string";
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.string";
/**
* Checks if the value is of string type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
return typeof value === "string";
};
constructor(options, validations) {
super(options, validations || [stringRule()]);
}
/**
* Validates the value to be a valid URL
*/
url(...args) {
return this.use(urlRule(...args));
}
/**
* Validates the value to be an active URL
*/
activeUrl() {
return this.use(activeUrlRule());
}
/**
* Validates the value to be a valid email address
*/
email(...args) {
return this.use(emailRule(...args));
}
/**
* Validates the value to be a valid mobile number
*/
mobile(...args) {
return this.use(mobileRule(...args));
}
/**
* Validates the value to be a valid IP address.
*/
ipAddress(version) {
return this.use(ipAddressRule(version ? { version } : void 0));
}
/**
* Validates the value to be a valid hex color code
*/
hexCode() {
return this.use(hexCodeRule());
}
/**
* Validates the value against a regular expression
*/
regex(expression) {
return this.use(regexRule(expression));
}
/**
* Validates the value to contain only letters
*/
alpha(options) {
return this.use(alphaRule(options));
}
/**
* Validates the value to contain only letters and
* numbers
*/
alphaNumeric(options) {
return this.use(alphaNumericRule(options));
}
/**
* Enforce a minimum length on a string field
*/
minLength(expectedLength) {
return this.use(minLengthRule3({ min: expectedLength }));
}
/**
* Enforce a maximum length on a string field
*/
maxLength(expectedLength) {
return this.use(maxLengthRule3({ max: expectedLength }));
}
/**
* Enforce a fixed length on a string field
*/
fixedLength(expectedLength) {
return this.use(fixedLengthRule3({ size: expectedLength }));
}
/**
* Ensure the field under validation is confirmed by
* having another field with the same name.
*/
confirmed(options) {
return this.use(confirmedRule(options));
}
/**
* Trims whitespaces around the string value
*/
trim() {
return this.use(trimRule());
}
/**
* Normalizes the email address
*/
normalizeEmail(options) {
return this.use(normalizeEmailRule(options));
}
/**
* Converts the field value to UPPERCASE.
*/
toUpperCase() {
return this.use(toUpperCaseRule());
}
/**
* Converts the field value to lowercase.
*/
toLowerCase() {
return this.use(toLowerCaseRule());
}
/**
* Converts the field value to camelCase.
*/
toCamelCase() {
return this.use(toCamelCaseRule());
}
/**
* Escape string for HTML entities
*/
escape() {
return this.use(escapeRule());
}
/**
* Normalize a URL
*/
normalizeUrl(...args) {
return this.use(normalizeUrlRule(...args));
}
/**
* Ensure the value starts with the pre-defined substring
*/
startsWith(substring) {
return this.use(startsWithRule({ substring }));
}
/**
* Ensure the value ends with the pre-defined substring
*/
endsWith(substring) {
return this.use(endsWithRule({ substring }));
}
/**
* Ensure the value ends with the pre-defined substring
*/
sameAs(otherField) {
return this.use(sameAsRule2({ otherField }));
}
/**
* Ensure the value ends with the pre-defined substring
*/
notSameAs(otherField) {
return this.use(notSameAsRule2({ otherField }));
}
/**
* Ensure the field's value under validation is a subset of the pre-defined list.
*/
in(choices) {
return this.use(inRule({ choices }));
}
/**
* Ensure the field's value under validation is not inside the pre-defined list.
*/
notIn(list) {
return this.use(notInRule({ list }));
}
/**
* Validates the value to be a valid credit card number
*/
creditCard(...args) {
return this.use(creditCardRule(...args));
}
/**
* Validates the value to be a valid passport number
*/
passport(...args) {
return this.use(passportRule(...args));
}
/**
* Validates the value to be a valid postal code
*/
postalCode(...args) {
return this.use(postalCodeRule(...args));
}
/**
* Validates the value to be a valid UUID
*/
uuid(...args) {
return this.use(uuidRule(...args));
}
/**
* Validates the value to be a valid ULID
*/
ulid() {
return this.use(ulidRule());
}
/**
* Validates the value contains ASCII characters only
*/
ascii() {
return this.use(asciiRule());
}
/**
* Validates the value to be a valid IBAN number
*/
iban() {
return this.use(ibanRule());
}
/**
* Validates the value to be a valid JWT token
*/
jwt() {
return this.use(jwtRule());
}
/**
* Ensure the value is a string with latitude and longitude coordinates
*/
coordinates() {
return this.use(coordinatesRule());
}
/**
* Clones the VineString schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineString(this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/number/rules.ts
var numberRule = createRule((value, options, field) => {
const valueAsNumber = options.strict ? value : helpers.asNumber(value);
if (typeof valueAsNumber !== "number" || Number.isNaN(valueAsNumber) || valueAsNumber === Number.POSITIVE_INFINITY || valueAsNumber === Number.NEGATIVE_INFINITY) {
field.report(messages.number, "number", field);
return;
}
field.mutate(valueAsNumber, field);
});
var minRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value < options.min) {
field.report(messages.min, "min", field, options);
}
});
var maxRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value > options.max) {
field.report(messages.max, "max", field, options);
}
});
var rangeRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (value < options.min || value > options.max) {
field.report(messages.range, "range", field, options);
}
});
var positiveRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (value < 0) {
field.report(messages.positive, "positive", field);
}
});
var negativeRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (value >= 0) {
field.report(messages.negative, "negative", field);
}
});
var decimalRule = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!helpers.isDecimal(String(value), {
force_decimal: options.range[0] !== 0,
decimal_digits: options.range.join(",")
})) {
field.report(messages.decimal, "decimal", field, { digits: options.range.join("-") });
}
});
var withoutDecimalsRule = createRule((value, _, field) => {
if (!field.isValid) {
return;
}
if (!Number.isInteger(value)) {
field.report(messages.withoutDecimals, "withoutDecimals", field);
}
});
var inRule2 = createRule((value, options, field) => {
if (!field.isValid) {
return;
}
if (!options.values.includes(value)) {
field.report(messages["number.in"], "in", field, options);
}
});
// src/schema/number/main.ts
var VineNumber = class _VineNumber extends BaseLiteralType {
/**
* Default collection of number rules
*/
static rules = {
in: inRule2,
max: maxRule,
min: minRule,
range: rangeRule,
number: numberRule,
decimal: decimalRule,
negative: negativeRule,
positive: positiveRule,
withoutDecimals: withoutDecimalsRule
};
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "number";
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.number";
/**
* Checks if the value is of number type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
const valueAsNumber = helpers.asNumber(value);
return !Number.isNaN(valueAsNumber);
};
constructor(options, validations) {
super(options, validations || [numberRule(options || {})]);
}
/**
* Enforce a minimum value for the number input
*/
min(value) {
return this.use(minRule({ min: value }));
}
/**
* Enforce a maximum value for the number input
*/
max(value) {
return this.use(maxRule({ max: value }));
}
/**
* Enforce value to be within the range of minimum and maximum output.
*/
range(value) {
return this.use(rangeRule({ min: value[0], max: value[1] }));
}
/**
* Enforce the value be a positive number
*/
positive() {
return this.use(positiveRule());
}
/**
* Enforce the value be a negative number
*/
negative() {
return this.use(negativeRule());
}
/**
* Enforce the value to have fixed or range
* of decimal places
*/
decimal(range) {
return this.use(decimalRule({ range: Array.isArray(range) ? range : [range] }));
}
/**
* Enforce the value to be an integer (aka without decimals)
*/
withoutDecimals() {
return this.use(withoutDecimalsRule());
}
/**
* Clones the VineNumber schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineNumber(this.cloneOptions(), this.cloneValidations());
}
/**
* Enforce the value to be in a list of allowed values
*/
in(values) {
return this.use(inRule2({ values }));
}
};
// src/schema/boolean/rules.ts
var booleanRule = createRule((value, options, field) => {
const valueAsBoolean = options.strict === true ? value : helpers.asBoolean(value);
if (typeof valueAsBoolean !== "boolean") {
field.report(messages.boolean, "boolean", field);
return;
}
field.mutate(valueAsBoolean, field);
});
// src/schema/boolean/main.ts
var VineBoolean = class _VineBoolean extends BaseLiteralType {
/**
* Default collection of boolean rules
*/
static rules = {
boolean: booleanRule
};
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "boolean";
/**
* The property must be implemented for "unionOfTypes"
*/
[UNIQUE_NAME] = "vine.boolean";
/**
* Checks if the value is of boolean type. The method must be
* implemented for "unionOfTypes"
*/
[IS_OF_TYPE] = (value) => {
const valueAsBoolean = this.options.strict === true ? value : helpers.asBoolean(value);
return typeof valueAsBoolean === "boolean";
};
constructor(options, validations) {
super(options, validations || [booleanRule(options || {})]);
}
/**
* Clones the VineBoolean schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineBoolean(this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/literal/rules.ts
var equalsRule2 = createRule((value, options, field) => {
let input = value;
if (typeof options.expectedValue === "boolean") {
input = helpers.asBoolean(value);
} else if (typeof options.expectedValue === "number") {
input = helpers.asNumber(value);
}
if (input !== options.expectedValue) {
field.report(messages.literal, "literal", field, options);
return;
}
field.mutate(input, field);
});
// src/schema/literal/main.ts
var VineLiteral = class _VineLiteral extends BaseLiteralType {
/**
* Default collection of literal rules
*/
static rules = {
equals: equalsRule2
};
#value;
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "literal";
constructor(value, options, validations) {
super(options, validations || [equalsRule2({ expectedValue: value })]);
this.#value = value;
}
/**
* Clones the VineLiteral schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineLiteral(this.#value, this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/accepted/rules.ts
var ACCEPTED_VALUES = ["on", "1", "yes", "true", true, 1];
var acceptedRule = createRule((value, _, field) => {
if (!ACCEPTED_VALUES.includes(value)) {
field.report(messages.accepted, "accepted", field);
}
});
// src/schema/accepted/main.ts
var VineAccepted = class _VineAccepted extends BaseLiteralType {
/**
* Default collection of accepted rules
*/
static rules = {
accepted: acceptedRule
};
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "checkbox";
constructor(options, validations) {
super(options, validations || [acceptedRule()]);
}
/**
* Clones the VineAccepted schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineAccepted(this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/object/group.ts
var ObjectGroup = class _ObjectGroup {
#conditionals;
#otherwiseCallback = (_, field) => {
field.report(messages.unionGroup, "unionGroup", field);
};
constructor(conditionals) {
this.#conditionals = conditionals;
}
/**
* Clones the ObjectGroup schema type.
*/
clone() {
const cloned = new _ObjectGroup(this.#conditionals);
cloned.otherwise(this.#otherwiseCallback);
return cloned;
}
/**
* Define a fallback method to invoke when all of the group conditions
* fail. You may use this method to report an error.
*/
otherwise(callback) {
this.#otherwiseCallback = callback;
return this;
}
/**
* Compiles the group
*/
[PARSE](refs, options) {
return {
type: "group",
elseConditionalFnRefId: refs.trackConditional(this.#otherwiseCallback),
conditions: this.#conditionals.map((conditional) => conditional[PARSE](refs, options))
};
}
};
// src/schema/object/conditional.ts
var GroupConditional = class {
/**
* Properties to merge when conditonal is true
*/
#properties;
/**
* Conditional to evaluate
*/
#conditional;
constructor(conditional, properties) {
this.#properties = properties;
this.#conditional = conditional;
}
/**
* Compiles to a union conditional
*/
[PARSE](refs, options) {
return {
schema: {
type: "sub_object",
properties: Object.keys(this.#properties).map((property) => {
return this.#properties[property][PARSE](property, refs, options);
}),
groups: []
// Compiler allows nested groups, but we are not implementing it
},
conditionalFnRefId: refs.trackConditional(this.#conditional)
};
}
};
// src/schema/object/group_builder.ts
function group(conditionals) {
return new ObjectGroup(conditionals);
}
group.if = function groupIf(conditon, properties) {
return new GroupConditional(conditon, properties);
};
group.else = function groupElse(properties) {
return new GroupConditional(() => true, properties);
};
// src/schema/enum/native_enum.ts
var VineNativeEnum = class _VineNativeEnum extends BaseLiteralType {
/**
* Default collection of enum rules
*/
static rules = {
enum: enumRule
};
#values;
/**
* The subtype of the literal schema field
*/
[SUBTYPE] = "enum";
constructor(values, options, validations) {
super(options, validations || [enumRule({ choices: Object.values(values) })]);
this.#values = values;
}
/**
* Clones the VineNativeEnum schema type. The applied options
* and validations are copied to the new instance
*/
clone() {
return new _VineNativeEnum(this.#values, this.cloneOptions(), this.cloneValidations());
}
};
// src/schema/union_of_types/main.ts
import camelcase8 from "camelcase";
var VineUnionOfTypes = class _VineUnionOfTypes {
#schemas;
#otherwiseCallback = (_, field) => {
field.report(messages.unionOfTypes, "unionOfTypes", field);
};
constructor(schemas) {
this.#schemas = schemas;
}
/**
* Define a fallback method to invoke when all of the union conditions
* fail. You may use this method to report an error.
*/
otherwise(callback) {
this.#otherwiseCallback = callback;
return this;
}
/**
* Clones the VineUnionOfTypes schema type.
*/
clone() {
const cloned = new _VineUnionOfTypes(this.#schemas);
cloned.otherwise(this.#otherwiseCallback);
return cloned;
}
/**
* Compiles to a union
*/
[PARSE](propertyName, refs, options) {
return {
type: "union",
fieldName: propertyName,
propertyName: options.toCamelCase ? camelcase8(propertyName) : propertyName,
elseConditionalFnRefId: refs.trackConditional(this.#otherwiseCallback),
conditions: this.#schemas.map((schema) => {
return {
conditionalFnRefId: refs.trackConditional((value, field) => {
return schema[IS_OF_TYPE](value, field);
}),
schema: schema[PARSE](propertyName, refs, options)
};
})
};
}
};
// src/schema/builder.ts
var SchemaBuilder = class extends Macroable3 {
/**
* Define a sub-object as a union
*/
group = group;
/**
* Define a union value
*/
union = union;
/**
* Define a string value
*/
string() {
return new VineString();
}
/**
* Define a boolean value
*/
boolean(options) {
return new VineBoolean(options);
}
/**
* Validate a checkbox to be checked
*/
accepted() {
return new VineAccepted();
}
/**
* Define a number value
*/
number(options) {
return new VineNumber(options);
}
/**
* Define a datetime value
*/
date(options) {
return new VineDate(options);
}
/**
* Define a schema type in which the input value
* matches the pre-defined value
*/
literal(value) {
return new VineLiteral(value);
}
/**
* Define an object with known properties. You may call "allowUnknownProperties"
* to merge unknown properties.
*/
object(properties) {
return new VineObject(properties);
}
/**
* Define an array field and validate its children elements.
*/
array(schema) {
return new VineArray(schema);
}
/**
* Define an array field with known length and each children
* element may have its own schema.
*/
tuple(schemas) {
return new VineTuple(schemas);
}
/**
* Define an object field with key-value pair. The keys in
* a record are unknown and values can be of a specific
* schema type.
*/
record(schema) {
return new VineRecord(schema);
}
enum(values) {
if (Array.isArray(values) || typeof values === "function") {
return new VineEnum(values);
}
return new VineNativeEnum(values);
}
/**
* Allow the field value to be anything
*/
any() {
return new VineAny();
}
/**
* Define a union of unique schema types.
*/
unionOfTypes(schemas) {
const schemasInUse = /* @__PURE__ */ new Set();
schemas.forEach((schema) => {
if (!schema[IS_OF_TYPE] || !schema[UNIQUE_NAME]) {
throw new Error(
`Cannot use "${schema.constructor.name}". The schema type is not compatible for use with "vine.unionOfTypes"`
);
}
if (schemasInUse.has(schema[UNIQUE_NAME])) {
throw new Error(
`Cannot use duplicate schema "${schema[UNIQUE_NAME]}". "vine.unionOfTypes" needs distinct schema types only`
);
}
schemasInUse.add(schema[UNIQUE_NAME]);
});
schemasInUse.clear();
return new VineUnionOfTypes(schemas);
}
};
// src/vine/validator.ts
import { Compiler, refsBuilder } from "@vinejs/compiler";
var COMPILER_ERROR_MESSAGES = {
required: messages.required,
array: messages.array,
object: messages.object
};
var VineValidator = class {
/**
* Reference to the compiled schema
*/
#compiled;
/**
* Messages provider to use on the validator
*/
messagesProvider;
/**
* Error reporter to use on the validator
*/
errorReporter;
/**
* Parses schema to compiler nodes.
*/
#parse(schema) {
const refs = refsBuilder();
return {
compilerNode: {
type: "root",
schema: schema[PARSE]("", refs, { toCamelCase: false })
},
refs: refs.toJSON()
};
}
constructor(schema, options) {
const { compilerNode, refs } = this.#parse(schema);
this.#compiled = { schema: compilerNode, refs };
const metaDataValidator = options.metaDataValidator;
const validateFn = new Compiler(compilerNode, {
convertEmptyStringsToNull: options.convertEmptyStringsToNull,
messages: COMPILER_ERROR_MESSAGES
}).compile();
this.errorReporter = options.errorReporter;
this.messagesProvider = options.messagesProvider;
if (metaDataValidator) {
this.validate = (data, validateOptions) => {
let normalizedOptions = validateOptions ?? {};
const meta = normalizedOptions.meta ?? {};
const errorReporter = normalizedOptions.errorReporter ?? this.errorReporter;
const messagesProvider = normalizedOptions.messagesProvider ?? this.messagesProvider;
metaDataValidator(meta);
return validateFn(data, meta, refs, messagesProvider, errorReporter());
};
} else {
this.validate = (data, validateOptions) => {
let normalizedOptions = validateOptions ?? {};
const meta = normalizedOptions.meta ?? {};
const errorReporter = normalizedOptions.errorReporter ?? this.errorReporter;
const messagesProvider = normalizedOptions.messagesProvider ?? this.messagesProvider;
return validateFn(data, meta, refs, messagesProvider, errorReporter());
};
}
}
/**
* Performs validation without throwing the validation
* exception. Instead, the validation errors are
* returned as the first argument.
*
*
* ```ts
* await validator.tryValidate(data)
* await validator.tryValidate(data, { meta: {} })
*
* await validator.tryValidate(data, {
* meta: { userId: auth.user.id },
* errorReporter,
* messagesProvider
* })
* ```
*
*/
async tryValidate(data, ...[options]) {
try {
const result = await this.validate(data, options);
return [null, result];
} catch (error) {
if (error instanceof ValidationError) {
return [error, null];
}
throw error;
}
}
/**
* Returns the compiled schema and refs.
*/
toJSON() {
const { schema, refs } = this.#compiled;
return {
schema: structuredClone(schema),
refs
};
}
};
// src/vine/main.ts
var Vine = class extends SchemaBuilder {
/**
* Messages provider to use on the validator
*/
messagesProvider = new SimpleMessagesProvider(messages, fields);
/**
* Error reporter to use on the validator
*/
errorReporter = () => new SimpleErrorReporter();
/**
* Control whether or not to convert empty strings to null
*/
convertEmptyStringsToNull = false;
/**
* Helpers to perform type-checking or cast types keeping
* HTML forms serialization behavior in mind.
*/
helpers = helpers;
/**
* Convert a validation function to a Vine schema rule
*/
createRule = createRule;
/**
* Pre-compiles a schema into a validation function.
*
* ```ts
* const validate = vine.compile(schema)
* await validate({ data })
* ```
*/
compile(schema) {
return new VineValidator(schema, {
convertEmptyStringsToNull: this.convertEmptyStringsToNull,
messagesProvider: this.messagesProvider,
errorReporter: this.errorReporter
});
}
/**
* Define a callback to validate the metadata given to the validator
* at runtime
*/
withMetaData(callback) {
return {
compile: (schema) => {
return new VineValidator(schema, {
convertEmptyStringsToNull: this.convertEmptyStringsToNull,
messagesProvider: this.messagesProvider,
errorReporter: this.errorReporter,
metaDataValidator: callback
});
}
};
}
/**
* Validate data against a schema. Optionally, you can define
* error messages, fields, a custom messages provider,
* or an error reporter.
*
* ```ts
* await vine.validate({ schema, data })
* await vine.validate({ schema, data, messages, fields })
*
* await vine.validate({ schema, data, messages, fields }, {
* errorReporter
* })
* ```
*/
validate(options) {
const validator = this.compile(options.schema);
return validator.validate(options.data, options);
}
/**
* Validate data against a schema without throwing the
* "ValidationError" exception. Instead the validation
* errors are returned within the return value.
*
* ```ts
* await vine.tryValidate({ schema, data })
* await vine.tryValidate({ schema, data, messages, fields })
*
* await vine.tryValidate({ schema, data, messages, fields }, {
* errorReporter
* })
* ```
*/
tryValidate(options) {
const validator = this.compile(options.schema);
return validator.tryValidate(options.data, options);
}
};
// index.ts
var vine = new Vine();
var index_default = vine;
export {
symbols_exports,
BaseLiteralType,
VineAny,
VineEnum,
VineDate,
VineUnion,
BaseModifiersType2 as BaseModifiersType,
BaseType,
VineTuple,
VineArray,
VineObject,
VineRecord,
VineString,
VineNumber,
VineBoolean,
VineLiteral,
VineAccepted,
VineNativeEnum,
VineValidator,
Vine,
index_default
};