New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

req-trapper

Package Overview
Dependencies
Maintainers
0
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

req-trapper - npm Package Compare versions

Comparing version
1.1.0
to
1.1.1
+28
-3
dist/ErrorMessages.js

@@ -26,9 +26,34 @@ "use strict";

module.exports = __toCommonJS(ErrorMessages_exports);
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});
var ErrorMessages_default = ErrorMessages;
//# sourceMappingURL=ErrorMessages.js.map
+1
-1

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/ErrorMessages.ts"],"sourcesContent":["const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAM,gBAAqB,OAAO,OAAO;AAAA,EACrC,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,UAAU;AACd,CAAC;AAED,IAAO,wBAAQ;","names":[]}
{"version":3,"sources":["../src/ErrorMessages.ts"],"sourcesContent":["const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAM,gBAAqB,uBAAO,OAAO;AAAA,EACrC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,KAAK;AAAA,EACL,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,sBAAsB;AAC1B,CAAC;AAED,IAAO,wBAAQ;","names":[]}
// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -8,0 +33,0 @@ var ErrorMessages_default = ErrorMessages;

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/ErrorMessages.ts"],"sourcesContent":["const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;"],"mappings":";AAAA,IAAM,gBAAqB,OAAO,OAAO;AAAA,EACrC,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,UAAU;AACd,CAAC;AAED,IAAO,wBAAQ;","names":[]}
{"version":3,"sources":["../src/ErrorMessages.ts"],"sourcesContent":["const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;"],"mappings":";AAAA,IAAM,gBAAqB,uBAAO,OAAO;AAAA,EACrC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,KAAK;AAAA,EACL,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,sBAAsB;AAC1B,CAAC;AAED,IAAO,wBAAQ;","names":[]}

@@ -1,21 +0,33 @@

declare class Helpers implements IHelpers {
validations: any;
constructor({ validations }: any);
private canEscapeValidation;
declare class Helpers {
exists(value: any): boolean;
isEmail(value: string): boolean;
minimumOf(value: string | number, min: string | number): boolean;
maximumOf(value: string | number, max: number): boolean;
isInArray(value: string, options: string): boolean;
isNumber(value: any): boolean;
minimumOf(value: string, num: number): boolean;
maximumOf(value: string, num: number): boolean;
isInArray(value: string, arrayString: string): boolean;
isGreaterThanNum(value: string | number, num: number): boolean;
isGreaterThanNum(value: any, minValue: string | number): boolean;
isUrl(value: string): boolean;
isBoolean(value: any): boolean;
isAlpha(value: string): boolean;
isAlphaNum(value: string): boolean;
isArray(value: any): boolean;
isJson(value: string): boolean;
isDate(value: string): boolean;
isAfter(value: string, compareDate: string): boolean;
isBefore(value: string, compareDate: string): boolean;
isDigits(value: string, digits: string | number): boolean;
isDigitsBetween(value: string, minMax: string): boolean;
isUnique(value: string, tableColumn: string): boolean;
existsInDb(value: string, tableColumn: string): boolean;
isImage(value: any): boolean;
isFile(value: any): boolean;
isMimeType(value: any, mimeTypes: string): boolean;
requiredIf(condition: any, value: any): boolean;
requiredUnless(condition: any, value: any): boolean;
requiredWith(condition: any, value: any): boolean;
requiredWithAll(requestBody: any, attributes: string, value: any): boolean;
requiredWithout(condition: any, value: any): boolean;
requiredWithoutAll(requestBody: any, attributes: string, value: any): boolean;
}
interface IHelpers {
exists: (value: any) => boolean;
isNumber: (value: any) => boolean;
minimumOf: (value: any, num: number) => boolean;
maximumOf: (value: any, num: number) => boolean;
isInArray: (value: any, arrayString: any) => boolean;
isGreaterThanNum: (value: string | number, num: number) => boolean;
}
export { type IHelpers, Helpers as default };
export { Helpers as default };

@@ -1,21 +0,33 @@

declare class Helpers implements IHelpers {
validations: any;
constructor({ validations }: any);
private canEscapeValidation;
declare class Helpers {
exists(value: any): boolean;
isEmail(value: string): boolean;
minimumOf(value: string | number, min: string | number): boolean;
maximumOf(value: string | number, max: number): boolean;
isInArray(value: string, options: string): boolean;
isNumber(value: any): boolean;
minimumOf(value: string, num: number): boolean;
maximumOf(value: string, num: number): boolean;
isInArray(value: string, arrayString: string): boolean;
isGreaterThanNum(value: string | number, num: number): boolean;
isGreaterThanNum(value: any, minValue: string | number): boolean;
isUrl(value: string): boolean;
isBoolean(value: any): boolean;
isAlpha(value: string): boolean;
isAlphaNum(value: string): boolean;
isArray(value: any): boolean;
isJson(value: string): boolean;
isDate(value: string): boolean;
isAfter(value: string, compareDate: string): boolean;
isBefore(value: string, compareDate: string): boolean;
isDigits(value: string, digits: string | number): boolean;
isDigitsBetween(value: string, minMax: string): boolean;
isUnique(value: string, tableColumn: string): boolean;
existsInDb(value: string, tableColumn: string): boolean;
isImage(value: any): boolean;
isFile(value: any): boolean;
isMimeType(value: any, mimeTypes: string): boolean;
requiredIf(condition: any, value: any): boolean;
requiredUnless(condition: any, value: any): boolean;
requiredWith(condition: any, value: any): boolean;
requiredWithAll(requestBody: any, attributes: string, value: any): boolean;
requiredWithout(condition: any, value: any): boolean;
requiredWithoutAll(requestBody: any, attributes: string, value: any): boolean;
}
interface IHelpers {
exists: (value: any) => boolean;
isNumber: (value: any) => boolean;
minimumOf: (value: any, num: number) => boolean;
maximumOf: (value: any, num: number) => boolean;
isInArray: (value: any, arrayString: any) => boolean;
isGreaterThanNum: (value: string | number, num: number) => boolean;
}
export { type IHelpers, Helpers as default };
export { Helpers as default };

@@ -23,52 +23,118 @@ "use strict";

__export(Helpers_exports, {
default: () => Helpers_default
default: () => Helpers
});
module.exports = __toCommonJS(Helpers_exports);
var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
//# sourceMappingURL=Helpers.js.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../src/functionality/Helpers.ts"],"sourcesContent":["class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAM,UAAN,MAAkC;AAAA,EAG9B,YAAY,EAAC,YAAW,GAAQ;AAC5B,SAAK,cAAc;AAAA,EACvB;AAAA;AAAA,EAIQ,oBAAoB,OAAY;AACpC,UAAM,aAAa,KAAK,YAAY,SAAS,UAAU;AACvD,WAAO,CAAC,SAAS,CAAC;AAAA,EACtB;AAAA,EAEA,OAAO,OAAY;AACf,WAAO,CAAC,CAAC;AAAA,EACb;AAAA,EAEA,SAAS,OAAY;AACjB,WAAO,OAAO,UAAU,CAAC,KAAK,KAAK,KAAK,oBAAoB,KAAK;AAAA,EACrE;AAAA,EAEA,UAAU,OAAe,KAAa;AAClC,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,aAAO,OAAO,UAAU;AAAA,IAC5B;AACA,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAAe,KAAa;AAClC,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,aAAO,OAAO,UAAU;AAAA,IAC5B;AACA,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAAe,aAAqB;AAC1C,WAAO,KAAK,OAAO,KAAK,KACnB,MAAM;AACH,aAAO,OAAO,WAAW,KAAK,MAAM;AAChC,cAAM,QAAQ,OAAO,WAAW,EAAE,MAAM,GAAG;AAC3C,eAAO,MAAM,SAAS,KAAK;AAAA,MAC/B,GAAG,IAAI;AAAA,IACX,GAAG,IAAI,KAAK,oBAAoB,KAAK;AAAA,EAC7C;AAAA,EAGA,iBAAiB,OAAwB,KAAa;AAClD,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,UAAI,KAAK,SAAS,KAAK,GAAG;AACtB,eAAO,CAAC,QAAQ;AAAA,MACpB,OAAO;AACH,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO,KAAK,oBAAoB,KAAY;AAAA,EAChD;AACJ;AAYA,IAAO,kBAAQ;","names":[]}
{"version":3,"sources":["../../src/functionality/Helpers.ts"],"sourcesContent":["export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}"],"mappings":"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","names":[]}
// src/functionality/Helpers.ts
var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
export {
Helpers_default as default
Helpers as default
};
//# sourceMappingURL=Helpers.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../src/functionality/Helpers.ts"],"sourcesContent":["class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers"],"mappings":";AAAA,IAAM,UAAN,MAAkC;AAAA,EAG9B,YAAY,EAAC,YAAW,GAAQ;AAC5B,SAAK,cAAc;AAAA,EACvB;AAAA;AAAA,EAIQ,oBAAoB,OAAY;AACpC,UAAM,aAAa,KAAK,YAAY,SAAS,UAAU;AACvD,WAAO,CAAC,SAAS,CAAC;AAAA,EACtB;AAAA,EAEA,OAAO,OAAY;AACf,WAAO,CAAC,CAAC;AAAA,EACb;AAAA,EAEA,SAAS,OAAY;AACjB,WAAO,OAAO,UAAU,CAAC,KAAK,KAAK,KAAK,oBAAoB,KAAK;AAAA,EACrE;AAAA,EAEA,UAAU,OAAe,KAAa;AAClC,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,aAAO,OAAO,UAAU;AAAA,IAC5B;AACA,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAAe,KAAa;AAClC,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,aAAO,OAAO,UAAU;AAAA,IAC5B;AACA,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAAe,aAAqB;AAC1C,WAAO,KAAK,OAAO,KAAK,KACnB,MAAM;AACH,aAAO,OAAO,WAAW,KAAK,MAAM;AAChC,cAAM,QAAQ,OAAO,WAAW,EAAE,MAAM,GAAG;AAC3C,eAAO,MAAM,SAAS,KAAK;AAAA,MAC/B,GAAG,IAAI;AAAA,IACX,GAAG,IAAI,KAAK,oBAAoB,KAAK;AAAA,EAC7C;AAAA,EAGA,iBAAiB,OAAwB,KAAa;AAClD,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,UAAI,KAAK,SAAS,KAAK,GAAG;AACtB,eAAO,CAAC,QAAQ;AAAA,MACpB,OAAO;AACH,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO,KAAK,oBAAoB,KAAY;AAAA,EAChD;AACJ;AAYA,IAAO,kBAAQ;","names":[]}
{"version":3,"sources":["../../src/functionality/Helpers.ts"],"sourcesContent":["export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}"],"mappings":";AAAA,IAAqB,UAArB,MAA6B;AAAA,EACzB,OAAO,OAAY;AACf,WAAO,UAAU,UAAa,UAAU,QAAQ,UAAU;AAAA,EAC9D;AAAA,EAEA,QAAQ,OAAe;AACnB,UAAM,KAAK;AACX,WAAO,GAAG,KAAK,OAAO,KAAK,EAAE,YAAY,CAAC;AAAA,EAC9C;AAAA,EAEA,UAAU,OAAwB,KAAsB;AACpD,QAAI,OAAQ,UAAU;AAAU,aAAO,MAAM,UAAU,OAAO,GAAG;AACjE,WAAO,SAAS,OAAO,GAAG;AAAA,EAC9B;AAAA,EAEA,UAAU,OAAwB,KAAa;AAC3C,QAAI,OAAQ,UAAU;AAAU,aAAO,MAAM,UAAU,OAAO,GAAG;AACjE,WAAO,SAAS,OAAO,GAAG;AAAA,EAC9B;AAAA,EAEA,UAAU,OAAe,SAAiB;AACtC,UAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,WAAO,MAAM,SAAS,KAAK;AAAA,EAC/B;AAAA,EAEA,SAAS,OAAY;AACjB,WAAO,CAAC,MAAM,OAAO,KAAK,CAAC;AAAA,EAC/B;AAAA,EAEA,iBAAiB,OAAY,UAA2B;AACpD,YAAQ,IAAI,KAAK;AACjB,YAAQ,IAAI,QAAQ;AACpB,WAAO,OAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,EAC1C;AAAA,EAEA,MAAM,OAAe;AACjB,UAAM,KAAK,IAAI;AAAA,MACX;AAAA,MAKsB;AAAA,IAC1B;AACA,WAAO,GAAG,KAAK,KAAK;AAAA,EACxB;AAAA,EAEA,UAAU,OAAY;AAClB,WAAO,UAAU,QAAQ,UAAU,SAAS,UAAU,UAAU,UAAU;AAAA,EAC9E;AAAA,EAEA,QAAQ,OAAe;AACnB,WAAO,cAAc,KAAK,KAAK;AAAA,EACnC;AAAA,EAEA,WAAW,OAAe;AACtB,WAAO,iBAAiB,KAAK,KAAK;AAAA,EACtC;AAAA,EAEA,QAAQ,OAAY;AAChB,WAAO,MAAM,QAAQ,KAAK;AAAA,EAC9B;AAAA,EAEA,OAAO,OAAe;AAClB,QAAI;AACA,WAAK,MAAM,KAAK;AAChB,aAAO;AAAA,IACX,SAAS,GAAG;AACR,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,OAAO,OAAe;AAClB,WAAO,CAAC,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,EACnC;AAAA,EAEA,QAAQ,OAAe,aAAqB;AACxC,WAAO,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,WAAW;AAAA,EACjD;AAAA,EAEA,SAAS,OAAe,aAAqB;AACzC,WAAO,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,WAAW;AAAA,EACjD;AAAA,EAEA,SAAS,OAAe,QAAyB;AAC7C,WAAO,MAAM,WAAW,OAAO,MAAM;AAAA,EACzC;AAAA,EAEA,gBAAgB,OAAe,QAAgB;AAC3C,UAAM,CAAC,KAAK,GAAG,IAAI,OAAO,MAAM,GAAG;AACnC,WAAO,MAAM,UAAU,OAAO,GAAG,KAAK,MAAM,UAAU,OAAO,GAAG;AAAA,EACpE;AAAA,EAEA,SAAS,OAAe,aAAqB;AAEzC,WAAO;AAAA,EACX;AAAA,EAEA,WAAW,OAAe,aAAqB;AAE3C,WAAO;AAAA,EACX;AAAA,EAEA,QAAQ,OAAY;AAEhB,UAAM,kBAAkB,CAAC,cAAc,aAAa,WAAW;AAC/D,WAAO,gBAAgB,SAAS,MAAM,QAAQ;AAAA,EAClD;AAAA,EAEA,OAAO,OAAY;AAEf,WAAO,iBAAiB,UAAU,iBAAiB;AAAA,EACvD;AAAA,EAEA,WAAW,OAAY,WAAmB;AACtC,UAAM,mBAAmB,UAAU,MAAM,GAAG;AAC5C,WAAO,iBAAiB,SAAS,MAAM,QAAQ;AAAA,EACnD;AAAA,EAEA,WAAW,WAAgB,OAAY;AACnC,WAAO,YAAY,KAAK,OAAO,KAAK,IAAI;AAAA,EAC5C;AAAA,EAEA,eAAe,WAAgB,OAAY;AACvC,WAAO,CAAC,YAAY,KAAK,OAAO,KAAK,IAAI;AAAA,EAC7C;AAAA,EAEA,aAAa,WAAgB,OAAY;AACrC,WAAO,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,IAAI;AAAA,EACzD;AAAA,EAEA,gBAAgB,aAAkB,YAAoB,OAAY;AAC9D,UAAM,aAAa,WAAW,MAAM,GAAG;AACvC,UAAM,aAAa,WAAW,MAAM,UAAQ,KAAK,OAAO,YAAY,IAAI,CAAC,CAAC;AAC1E,WAAO,aAAa,KAAK,OAAO,KAAK,IAAI;AAAA,EAC7C;AAAA,EAEA,gBAAgB,WAAgB,OAAY;AACxC,WAAO,CAAC,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,IAAI;AAAA,EAC1D;AAAA,EAEA,mBAAmB,aAAkB,YAAoB,OAAY;AACjE,UAAM,aAAa,WAAW,MAAM,GAAG;AACvC,UAAM,cAAc,WAAW,MAAM,UAAQ,CAAC,KAAK,OAAO,YAAY,IAAI,CAAC,CAAC;AAC5E,WAAO,cAAc,KAAK,OAAO,KAAK,IAAI;AAAA,EAC9C;AACJ;","names":[]}

@@ -5,13 +5,12 @@ import * as qs from 'qs';

import { RuleSet } from '../interfaces/RuleSet.mjs';
import Helpers from './Helpers.mjs';
/**
@classdesc Main class for request trapper.
This class is what initiates the whole process. More like the engine.
* @member req
* @member res
* @member next
* @member errors
* @member rules
* @member helpers
*/
type TCustomValidation = {
action: (value: string, args?: any) => any;
validation: string;
};
interface IReqTrapperConstructor {
customValidations?: TCustomValidation[];
helpers?: Helpers;
}
declare class ReqTrapper {

@@ -24,17 +23,11 @@ private req;

private rules;
private validations;
private customMessages;
private readonly customValidations;
private helpers;
constructor();
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
constructor({ customValidations, helpers }?: IReqTrapperConstructor);
private middleware;
setRules(rulesArray: RuleSet[]): void;
setCustomMessages(messages: {
[key: string]: string;
}): void;
validate(rulesArray: RuleSet[]): (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => void;

@@ -44,5 +37,5 @@ private handleValidation;

private isValid;
private outputError;
private getErrorMessage;
}
export { ReqTrapper };

@@ -5,13 +5,12 @@ import * as qs from 'qs';

import { RuleSet } from '../interfaces/RuleSet.js';
import Helpers from './Helpers.js';
/**
@classdesc Main class for request trapper.
This class is what initiates the whole process. More like the engine.
* @member req
* @member res
* @member next
* @member errors
* @member rules
* @member helpers
*/
type TCustomValidation = {
action: (value: string, args?: any) => any;
validation: string;
};
interface IReqTrapperConstructor {
customValidations?: TCustomValidation[];
helpers?: Helpers;
}
declare class ReqTrapper {

@@ -24,17 +23,11 @@ private req;

private rules;
private validations;
private customMessages;
private readonly customValidations;
private helpers;
constructor();
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
constructor({ customValidations, helpers }?: IReqTrapperConstructor);
private middleware;
setRules(rulesArray: RuleSet[]): void;
setCustomMessages(messages: {
[key: string]: string;
}): void;
validate(rulesArray: RuleSet[]): (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => void;

@@ -44,5 +37,5 @@ private handleValidation;

private isValid;
private outputError;
private getErrorMessage;
}
export { ReqTrapper };

@@ -28,7 +28,32 @@ "use strict";

// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -39,52 +64,118 @@ var ErrorMessages_default = ErrorMessages;

var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
// src/functionality/ReqTrapper.ts
var ReqTrapper = class _ReqTrapper {
constructor() {
constructor({ customValidations = [], helpers } = {}) {
this.req = null;

@@ -96,30 +187,20 @@ this.res = null;

this.rules = [];
this.validations = [];
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
this.customMessages = {};
this.customValidations = [];
this.middleware = (req, res, next) => {
req && (this.req = req) && (this.requestBody = req.body);
res && (this.res = res);
next && (this.next = next);
this.rules.map((rule) => {
this.handleValidation(rule);
return;
});
const errors = { ...this.errors };
this.errors = {};
if (Object.keys(errors)?.length > 0) {
res.status(400).json({ errors, success: false, data: null });
this.req = req;
this.requestBody = req.body;
this.res = res;
this.next = next;
this.rules.forEach((rule) => this.handleValidation(rule));
console.log(this.errors);
if (Object.keys(this.errors).length > 0) {
res.status(400).json({ errors: this.errors });
} else {
this.next && this.next();
next();
}
};
this.helpers = new Helpers_default({ validations: null });
this.customValidations = customValidations;
this.helpers = helpers;
this.errors = {};
}

@@ -133,29 +214,27 @@ setRules(rulesArray) {

}
// Helps with multi requests usage
setCustomMessages(messages) {
this.customMessages = messages;
}
validate(rulesArray) {
const newInstance = new _ReqTrapper();
newInstance.setRules(rulesArray);
return newInstance.middleware;
const instance = new _ReqTrapper({ customValidations: this.customValidations, helpers: new Helpers() });
instance.setRules(rulesArray);
return instance.middleware;
}
// TODO: Add to error message
// addValidation(name: string, callback: (value: string) => any) {
// this.customValidations.push({
// validation: name,
// action: callback,
// });
// }
handleValidation(rule) {
try {
console.log("ln 78 /n", this.errors);
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
this.helpers = new Helpers_default({ validations });
for (let validation of validations) {
const attribute = validation?.split(":")?.[1];
validation = validation?.split(":")?.[0];
if (!this.isValid(value, validation, attribute)) {
this.errors[rule?.name] = this.outputError(
rule?.name,
validation,
attribute
);
break;
}
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
for (let validation of validations) {
const [validationName, attribute] = validation.split(":");
const valid = this.isValid(value, validationName, attribute);
if (!valid) {
this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);
break;
}
} catch (e) {
console.error(e);
return e;
}

@@ -170,4 +249,4 @@ }

return this.helpers.exists(value);
case "number":
return this.helpers.isNumber(value);
case "email":
return this.helpers.isEmail(value);
case "min":

@@ -177,13 +256,69 @@ return this.helpers.minimumOf(value, attribute);

return this.helpers.maximumOf(value, attribute);
case "in_array":
case "in":
return this.helpers.isInArray(value, attribute);
case "number":
return this.helpers.isNumber(value);
case "greater_than":
return this.helpers.isGreaterThanNum(value, attribute);
case "nullable":
return true;
case "url":
return this.helpers.isUrl(value);
case "boolean":
return this.helpers.isBoolean(value);
case "alpha":
return this.helpers.isAlpha(value);
case "alpha_num":
return this.helpers.isAlphaNum(value);
case "array":
return Array.isArray(value);
case "json":
return this.helpers.isJson(value);
case "date":
return this.helpers.isDate(value);
case "after":
return this.helpers.isAfter(value, attribute);
case "before":
return this.helpers.isBefore(value, attribute);
case "unique":
return this.helpers.isUnique(value, attribute);
case "digits":
return this.helpers.isDigits(value, attribute);
case "digits_between":
return this.helpers.isDigitsBetween(value, attribute);
case "exists":
return this.helpers.existsInDb(value, attribute);
case "image":
return this.helpers.isImage(value);
case "file":
return this.helpers.isFile(value);
case "mimes":
return this.helpers.isMimeType(value, attribute);
case "required_if":
return this.helpers.requiredIf(this.requestBody?.[attribute], value);
case "required_unless":
return this.helpers.requiredUnless(this.requestBody?.[attribute], value);
case "required_with":
return this.helpers.requiredWith(this.requestBody?.[attribute], value);
case "required_with_all":
return this.helpers.requiredWithAll(this.requestBody, attribute, value);
case "required_without":
return this.helpers.requiredWithout(this.requestBody?.[attribute], value);
case "required_without_all":
return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);
default:
const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);
if (foundCustomValidation) {
return foundCustomValidation.action(value, attribute) ?? false;
}
return false;
}
}
outputError(field, validation, attribute) {
const errorMessage = ErrorMessages_default?.[validation.toUpperCase()].replace(":field", field).replace(":attribute", attribute);
return errorMessage ?? "Error message not yet defined";
getErrorMessage(field, validation, attribute) {
const customMessageKey = `${field}.${validation}`;
if (this.customMessages[customMessageKey]) {
return this.customMessages[customMessageKey];
}
const errorMessage = (ErrorMessages_default?.[validation.toUpperCase()] ?? "").replace(":field", field).replace(":attribute", attribute);
return errorMessage || "Validation error";
}

@@ -190,0 +325,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../src/functionality/ReqTrapper.ts","../../src/ErrorMessages.ts","../../src/functionality/Helpers.ts"],"sourcesContent":["import {NextFunction, Request, Response} from \"express\";\nimport {RuleSet} from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers, {IHelpers} from \"./Helpers\";\n\n// @Todo Allow custom validation\n// @Todo Add in more validations\n// Todo - Create means to skip validation if required is not set - @Done\n\n/**\n @classdesc Main class for request trapper.\n This class is what initiates the whole process. More like the engine.\n * @member req\n * @member res\n * @member next\n * @member errors\n * @member rules\n * @member helpers\n */\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: {[key: string]: any} = {};\n private rules: RuleSet[] = [];\n private validations: string[] = [];\n private helpers: Helpers;\n\n constructor() {\n this.helpers = new Helpers({validations: null})\n }\n\n /**\n\n ## The middleware\n This handles the request\n\n @param req Express Request\n @param res Express Response\n @param next Express NextFunction\n @returns void\n */\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n req && (this.req = req) && (this.requestBody = req.body);\n res && (this.res = res);\n next && (this.next = next);\n\n this.rules.map((rule: RuleSet) => {\n this.handleValidation(rule);\n return;\n });\n const errors = {...this.errors}\n this.errors = {};\n if (Object.keys(errors)?.length > 0) {\n res.status(400).json({errors, success: false, data: null});\n } else {\n this.next && this.next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n // Helps with multi requests usage\n validate(rulesArray: RuleSet[]) {\n const newInstance = new ReqTrapper();\n newInstance.setRules(rulesArray);\n return newInstance.middleware;\n }\n\n private handleValidation(rule: RuleSet) {\n try {\n console.log(\"ln 78 /n\",this.errors);\n const value = this.requestBody?.[rule?.name];\n\n const validations = this.explodeValidation(rule?.validation);\n this.helpers = new Helpers({validations})\n\n for (let validation of validations) {\n const attribute = validation?.split(\":\")?.[1];\n validation = validation?.split(\":\")?.[0];\n if (!this.isValid(value, validation, attribute)) {\n this.errors[rule?.name] = this.outputError(\n rule?.name,\n validation,\n attribute,\n );\n break; // break out of for loop\n }\n }\n\n } catch (e) {\n console.error(e)\n return e;\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any) {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in_array\":\n return this.helpers.isInArray(value, attribute);\n case \"nullable\":\n return true;\n default:\n return false;\n }\n }\n\n private outputError(\n field: string,\n validation: string,\n attribute?: string | number,\n ) {\n const errorMessage = ErrorMessages?.[validation.toUpperCase()]\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage ?? \"Error message not yet defined\";\n }\n\n\n\n}\n","const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;","class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers"],"mappings":"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","names":[]}
{"version":3,"sources":["../../src/functionality/ReqTrapper.ts","../../src/ErrorMessages.ts","../../src/functionality/Helpers.ts"],"sourcesContent":["import { NextFunction, Request, Response } from \"express\";\nimport { RuleSet } from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers from \"./Helpers\";\n\ntype TCustomValidation = {\n action: (value: string, args?: any) => any,\n validation: string\n};\n\ninterface IReqTrapperConstructor {\n customValidations?: TCustomValidation[],\n helpers?: Helpers\n}\n\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: { [key: string]: any } = {};\n private rules: RuleSet[] = [];\n private customMessages: { [key: string]: string } = {};\n private readonly customValidations: TCustomValidation[] = [];\n private helpers: Helpers;\n\n constructor({customValidations = [], helpers}: IReqTrapperConstructor = {}) {\n this.customValidations = customValidations;\n this.helpers = helpers!;\n this.errors = {}; // reset errors\n }\n\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n this.req = req;\n this.requestBody = req.body;\n this.res = res;\n this.next = next;\n\n\n\n this.rules.forEach((rule) => this.handleValidation(rule));\n console.log(this.errors)\n if (Object.keys(this.errors).length > 0) {\n res.status(400).json({ errors: this.errors });\n } else {\n\n next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n setCustomMessages(messages: { [key: string]: string }) {\n this.customMessages = messages;\n }\n\n validate(rulesArray: RuleSet[]) {\n const instance = new ReqTrapper({customValidations: this.customValidations, helpers: new Helpers()});\n instance.setRules(rulesArray);\n return instance.middleware;\n }\n\n // TODO: Add to error message\n // addValidation(name: string, callback: (value: string) => any) {\n // this.customValidations.push({\n // validation: name,\n // action: callback,\n // });\n // }\n\n private handleValidation(rule: RuleSet) {\n const value = this.requestBody?.[rule?.name];\n const validations = this.explodeValidation(rule?.validation);\n\n for (let validation of validations) {\n const [validationName, attribute] = validation.split(\":\");\n const valid = this.isValid(value, validationName, attribute);\n\n if (!valid) {\n this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);\n break;\n }\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any): boolean {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"email\":\n return this.helpers.isEmail(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in\":\n return this.helpers.isInArray(value, attribute);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"greater_than\":\n return this.helpers.isGreaterThanNum(value, attribute);\n case \"nullable\":\n return true;\n case \"url\":\n return this.helpers.isUrl(value);\n case \"boolean\":\n return this.helpers.isBoolean(value);\n case \"alpha\":\n return this.helpers.isAlpha(value);\n case \"alpha_num\":\n return this.helpers.isAlphaNum(value);\n case \"array\":\n return Array.isArray(value);\n case \"json\":\n return this.helpers.isJson(value);\n // case \"confirmed\":\n // return value === this.requestBody?.[`${rule.name}_confirmation`];\n case \"date\":\n return this.helpers.isDate(value);\n case \"after\":\n return this.helpers.isAfter(value, attribute);\n case \"before\":\n return this.helpers.isBefore(value, attribute);\n case \"unique\":\n return this.helpers.isUnique(value, attribute); // I will need to define the database check\n case \"digits\":\n return this.helpers.isDigits(value, attribute);\n case \"digits_between\":\n return this.helpers.isDigitsBetween(value, attribute);\n case \"exists\":\n return this.helpers.existsInDb(value, attribute); // I will need to define the database check\n case \"image\":\n return this.helpers.isImage(value); // Check for image types\n case \"file\":\n return this.helpers.isFile(value); // General file validation\n case \"mimes\":\n return this.helpers.isMimeType(value, attribute); // Check file MIME types\n case \"required_if\":\n return this.helpers.requiredIf(this.requestBody?.[attribute], value);\n case \"required_unless\":\n return this.helpers.requiredUnless(this.requestBody?.[attribute], value);\n case \"required_with\":\n return this.helpers.requiredWith(this.requestBody?.[attribute], value);\n case \"required_with_all\":\n return this.helpers.requiredWithAll(this.requestBody, attribute, value);\n case \"required_without\":\n return this.helpers.requiredWithout(this.requestBody?.[attribute], value);\n case \"required_without_all\":\n return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);\n default:\n const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);\n if (foundCustomValidation) {\n return foundCustomValidation.action(value, attribute) ?? false;\n }\n return false;\n }\n }\n\n private getErrorMessage(field: string, validation: string, attribute?: any) {\n const customMessageKey = `${field}.${validation}`;\n if (this.customMessages[customMessageKey]) {\n return this.customMessages[customMessageKey];\n }\n const errorMessage = (ErrorMessages?.[validation.toUpperCase()] ?? \"\")\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage || \"Validation error\";\n }\n}\n","const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;","export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}"],"mappings":"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","names":[]}
// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -12,52 +37,118 @@ var ErrorMessages_default = ErrorMessages;

var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
// src/functionality/ReqTrapper.ts
var ReqTrapper = class _ReqTrapper {
constructor() {
constructor({ customValidations = [], helpers } = {}) {
this.req = null;

@@ -69,30 +160,20 @@ this.res = null;

this.rules = [];
this.validations = [];
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
this.customMessages = {};
this.customValidations = [];
this.middleware = (req, res, next) => {
req && (this.req = req) && (this.requestBody = req.body);
res && (this.res = res);
next && (this.next = next);
this.rules.map((rule) => {
this.handleValidation(rule);
return;
});
const errors = { ...this.errors };
this.errors = {};
if (Object.keys(errors)?.length > 0) {
res.status(400).json({ errors, success: false, data: null });
this.req = req;
this.requestBody = req.body;
this.res = res;
this.next = next;
this.rules.forEach((rule) => this.handleValidation(rule));
console.log(this.errors);
if (Object.keys(this.errors).length > 0) {
res.status(400).json({ errors: this.errors });
} else {
this.next && this.next();
next();
}
};
this.helpers = new Helpers_default({ validations: null });
this.customValidations = customValidations;
this.helpers = helpers;
this.errors = {};
}

@@ -106,29 +187,27 @@ setRules(rulesArray) {

}
// Helps with multi requests usage
setCustomMessages(messages) {
this.customMessages = messages;
}
validate(rulesArray) {
const newInstance = new _ReqTrapper();
newInstance.setRules(rulesArray);
return newInstance.middleware;
const instance = new _ReqTrapper({ customValidations: this.customValidations, helpers: new Helpers() });
instance.setRules(rulesArray);
return instance.middleware;
}
// TODO: Add to error message
// addValidation(name: string, callback: (value: string) => any) {
// this.customValidations.push({
// validation: name,
// action: callback,
// });
// }
handleValidation(rule) {
try {
console.log("ln 78 /n", this.errors);
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
this.helpers = new Helpers_default({ validations });
for (let validation of validations) {
const attribute = validation?.split(":")?.[1];
validation = validation?.split(":")?.[0];
if (!this.isValid(value, validation, attribute)) {
this.errors[rule?.name] = this.outputError(
rule?.name,
validation,
attribute
);
break;
}
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
for (let validation of validations) {
const [validationName, attribute] = validation.split(":");
const valid = this.isValid(value, validationName, attribute);
if (!valid) {
this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);
break;
}
} catch (e) {
console.error(e);
return e;
}

@@ -143,4 +222,4 @@ }

return this.helpers.exists(value);
case "number":
return this.helpers.isNumber(value);
case "email":
return this.helpers.isEmail(value);
case "min":

@@ -150,13 +229,69 @@ return this.helpers.minimumOf(value, attribute);

return this.helpers.maximumOf(value, attribute);
case "in_array":
case "in":
return this.helpers.isInArray(value, attribute);
case "number":
return this.helpers.isNumber(value);
case "greater_than":
return this.helpers.isGreaterThanNum(value, attribute);
case "nullable":
return true;
case "url":
return this.helpers.isUrl(value);
case "boolean":
return this.helpers.isBoolean(value);
case "alpha":
return this.helpers.isAlpha(value);
case "alpha_num":
return this.helpers.isAlphaNum(value);
case "array":
return Array.isArray(value);
case "json":
return this.helpers.isJson(value);
case "date":
return this.helpers.isDate(value);
case "after":
return this.helpers.isAfter(value, attribute);
case "before":
return this.helpers.isBefore(value, attribute);
case "unique":
return this.helpers.isUnique(value, attribute);
case "digits":
return this.helpers.isDigits(value, attribute);
case "digits_between":
return this.helpers.isDigitsBetween(value, attribute);
case "exists":
return this.helpers.existsInDb(value, attribute);
case "image":
return this.helpers.isImage(value);
case "file":
return this.helpers.isFile(value);
case "mimes":
return this.helpers.isMimeType(value, attribute);
case "required_if":
return this.helpers.requiredIf(this.requestBody?.[attribute], value);
case "required_unless":
return this.helpers.requiredUnless(this.requestBody?.[attribute], value);
case "required_with":
return this.helpers.requiredWith(this.requestBody?.[attribute], value);
case "required_with_all":
return this.helpers.requiredWithAll(this.requestBody, attribute, value);
case "required_without":
return this.helpers.requiredWithout(this.requestBody?.[attribute], value);
case "required_without_all":
return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);
default:
const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);
if (foundCustomValidation) {
return foundCustomValidation.action(value, attribute) ?? false;
}
return false;
}
}
outputError(field, validation, attribute) {
const errorMessage = ErrorMessages_default?.[validation.toUpperCase()].replace(":field", field).replace(":attribute", attribute);
return errorMessage ?? "Error message not yet defined";
getErrorMessage(field, validation, attribute) {
const customMessageKey = `${field}.${validation}`;
if (this.customMessages[customMessageKey]) {
return this.customMessages[customMessageKey];
}
const errorMessage = (ErrorMessages_default?.[validation.toUpperCase()] ?? "").replace(":field", field).replace(":attribute", attribute);
return errorMessage || "Validation error";
}

@@ -163,0 +298,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../src/ErrorMessages.ts","../../src/functionality/Helpers.ts","../../src/functionality/ReqTrapper.ts"],"sourcesContent":["const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;","class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers","import {NextFunction, Request, Response} from \"express\";\nimport {RuleSet} from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers, {IHelpers} from \"./Helpers\";\n\n// @Todo Allow custom validation\n// @Todo Add in more validations\n// Todo - Create means to skip validation if required is not set - @Done\n\n/**\n @classdesc Main class for request trapper.\n This class is what initiates the whole process. More like the engine.\n * @member req\n * @member res\n * @member next\n * @member errors\n * @member rules\n * @member helpers\n */\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: {[key: string]: any} = {};\n private rules: RuleSet[] = [];\n private validations: string[] = [];\n private helpers: Helpers;\n\n constructor() {\n this.helpers = new Helpers({validations: null})\n }\n\n /**\n\n ## The middleware\n This handles the request\n\n @param req Express Request\n @param res Express Response\n @param next Express NextFunction\n @returns void\n */\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n req && (this.req = req) && (this.requestBody = req.body);\n res && (this.res = res);\n next && (this.next = next);\n\n this.rules.map((rule: RuleSet) => {\n this.handleValidation(rule);\n return;\n });\n const errors = {...this.errors}\n this.errors = {};\n if (Object.keys(errors)?.length > 0) {\n res.status(400).json({errors, success: false, data: null});\n } else {\n this.next && this.next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n // Helps with multi requests usage\n validate(rulesArray: RuleSet[]) {\n const newInstance = new ReqTrapper();\n newInstance.setRules(rulesArray);\n return newInstance.middleware;\n }\n\n private handleValidation(rule: RuleSet) {\n try {\n console.log(\"ln 78 /n\",this.errors);\n const value = this.requestBody?.[rule?.name];\n\n const validations = this.explodeValidation(rule?.validation);\n this.helpers = new Helpers({validations})\n\n for (let validation of validations) {\n const attribute = validation?.split(\":\")?.[1];\n validation = validation?.split(\":\")?.[0];\n if (!this.isValid(value, validation, attribute)) {\n this.errors[rule?.name] = this.outputError(\n rule?.name,\n validation,\n attribute,\n );\n break; // break out of for loop\n }\n }\n\n } catch (e) {\n console.error(e)\n return e;\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any) {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in_array\":\n return this.helpers.isInArray(value, attribute);\n case \"nullable\":\n return true;\n default:\n return false;\n }\n }\n\n private outputError(\n field: string,\n validation: string,\n attribute?: string | number,\n ) {\n const errorMessage = ErrorMessages?.[validation.toUpperCase()]\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage ?? \"Error message not yet defined\";\n }\n\n\n\n}\n"],"mappings":";AAAA,IAAM,gBAAqB,OAAO,OAAO;AAAA,EACrC,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,UAAU;AACd,CAAC;AAED,IAAO,wBAAQ;;;ACPf,IAAM,UAAN,MAAkC;AAAA,EAG9B,YAAY,EAAC,YAAW,GAAQ;AAC5B,SAAK,cAAc;AAAA,EACvB;AAAA;AAAA,EAIQ,oBAAoB,OAAY;AACpC,UAAM,aAAa,KAAK,YAAY,SAAS,UAAU;AACvD,WAAO,CAAC,SAAS,CAAC;AAAA,EACtB;AAAA,EAEA,OAAO,OAAY;AACf,WAAO,CAAC,CAAC;AAAA,EACb;AAAA,EAEA,SAAS,OAAY;AACjB,WAAO,OAAO,UAAU,CAAC,KAAK,KAAK,KAAK,oBAAoB,KAAK;AAAA,EACrE;AAAA,EAEA,UAAU,OAAe,KAAa;AAClC,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,aAAO,OAAO,UAAU;AAAA,IAC5B;AACA,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAAe,KAAa;AAClC,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,aAAO,OAAO,UAAU;AAAA,IAC5B;AACA,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAAe,aAAqB;AAC1C,WAAO,KAAK,OAAO,KAAK,KACnB,MAAM;AACH,aAAO,OAAO,WAAW,KAAK,MAAM;AAChC,cAAM,QAAQ,OAAO,WAAW,EAAE,MAAM,GAAG;AAC3C,eAAO,MAAM,SAAS,KAAK;AAAA,MAC/B,GAAG,IAAI;AAAA,IACX,GAAG,IAAI,KAAK,oBAAoB,KAAK;AAAA,EAC7C;AAAA,EAGA,iBAAiB,OAAwB,KAAa;AAClD,QAAI,KAAK,OAAO,KAAK,GAAG;AACpB,UAAI,KAAK,SAAS,KAAK,GAAG;AACtB,eAAO,CAAC,QAAQ;AAAA,MACpB,OAAO;AACH,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO,KAAK,oBAAoB,KAAY;AAAA,EAChD;AACJ;AAYA,IAAO,kBAAQ;;;AClDR,IAAM,aAAN,MAAM,YAAW;AAAA,EAUpB,cAAc;AATd,SAAQ,MAAsB;AAC9B,SAAQ,MAAuB;AAC/B,SAAQ,OAA4B;AACpC,SAAQ,cAA0B;AAClC,SAAQ,SAA+B,CAAC;AACxC,SAAQ,QAAmB,CAAC;AAC5B,SAAQ,cAAwB,CAAC;AAiBjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,aAAa,CAAC,KAAc,KAAe,SAAuB;AACtE,cAAQ,KAAK,MAAM,SAAS,KAAK,cAAc,IAAI;AACnD,cAAQ,KAAK,MAAM;AACnB,eAAS,KAAK,OAAO;AAErB,WAAK,MAAM,IAAI,CAAC,SAAkB;AAC9B,aAAK,iBAAiB,IAAI;AAC1B;AAAA,MACJ,CAAC;AACD,YAAM,SAAS,EAAC,GAAG,KAAK,OAAM;AAC9B,WAAK,SAAS,CAAC;AACf,UAAI,OAAO,KAAK,MAAM,GAAG,SAAS,GAAG;AACjC,YAAI,OAAO,GAAG,EAAE,KAAK,EAAC,QAAQ,SAAS,OAAO,MAAM,KAAI,CAAC;AAAA,MAC7D,OAAO;AACH,aAAK,QAAQ,KAAK,KAAK;AAAA,MAC3B;AAAA,IACJ;AA7BI,SAAK,UAAU,IAAI,gBAAQ,EAAC,aAAa,KAAI,CAAC;AAAA,EAClD;AAAA,EA8BA,SAAS,YAAuB;AAC5B,QAAI,CAAC,MAAM,QAAQ,UAAU,GAAG;AAC5B,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC7C,OAAO;AACH,WAAK,QAAQ;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA,EAGA,SAAS,YAAuB;AAC5B,UAAM,cAAc,IAAI,YAAW;AACnC,gBAAY,SAAS,UAAU;AAC/B,WAAO,YAAY;AAAA,EACvB;AAAA,EAEQ,iBAAiB,MAAe;AACpC,QAAI;AACA,cAAQ,IAAI,YAAW,KAAK,MAAM;AAClC,YAAM,QAAQ,KAAK,cAAc,MAAM,IAAI;AAE3C,YAAM,cAAc,KAAK,kBAAkB,MAAM,UAAU;AAC3D,WAAK,UAAU,IAAI,gBAAQ,EAAC,YAAW,CAAC;AAExC,eAAS,cAAc,aAAa;AAChC,cAAM,YAAY,YAAY,MAAM,GAAG,IAAI,CAAC;AAC5C,qBAAa,YAAY,MAAM,GAAG,IAAI,CAAC;AACvC,YAAI,CAAC,KAAK,QAAQ,OAAO,YAAY,SAAS,GAAG;AAC7C,eAAK,OAAO,MAAM,IAAI,IAAI,KAAK;AAAA,YAC3B,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACJ;AACA;AAAA,QACJ;AAAA,MACJ;AAAA,IAEJ,SAAS,GAAG;AACR,cAAQ,MAAM,CAAC;AACf,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEQ,kBAAkB,YAA8B;AACpD,WAAO,YAAY,MAAM,GAAG,KAAK,CAAC;AAAA,EACtC;AAAA,EAEQ,QAAQ,OAAY,YAAoB,WAAiB;AAC7D,YAAQ,YAAY;AAAA,MAChB,KAAK;AACD,eAAO,KAAK,QAAQ,OAAO,KAAK;AAAA,MACpC,KAAK;AACD,eAAO,KAAK,QAAQ,SAAS,KAAK;AAAA,MACtC,KAAK;AACD,eAAO,KAAK,QAAQ,UAAU,OAAO,SAAS;AAAA,MAClD,KAAK;AACD,eAAO,KAAK,QAAQ,UAAU,OAAO,SAAS;AAAA,MAClD,KAAK;AACD,eAAO,KAAK,QAAQ,UAAU,OAAO,SAAS;AAAA,MAClD,KAAK;AACD,eAAO;AAAA,MACX;AACI,eAAO;AAAA,IACf;AAAA,EACJ;AAAA,EAEQ,YACJ,OACA,YACA,WACF;AACE,UAAM,eAAe,wBAAgB,WAAW,YAAY,CAAC,EACxD,QAAQ,UAAU,KAAK,EACvB,QAAQ,cAAc,SAAS;AACpC,WAAO,gBAAgB;AAAA,EAC3B;AAIJ;","names":[]}
{"version":3,"sources":["../../src/ErrorMessages.ts","../../src/functionality/Helpers.ts","../../src/functionality/ReqTrapper.ts"],"sourcesContent":["const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;","export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}","import { NextFunction, Request, Response } from \"express\";\nimport { RuleSet } from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers from \"./Helpers\";\n\ntype TCustomValidation = {\n action: (value: string, args?: any) => any,\n validation: string\n};\n\ninterface IReqTrapperConstructor {\n customValidations?: TCustomValidation[],\n helpers?: Helpers\n}\n\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: { [key: string]: any } = {};\n private rules: RuleSet[] = [];\n private customMessages: { [key: string]: string } = {};\n private readonly customValidations: TCustomValidation[] = [];\n private helpers: Helpers;\n\n constructor({customValidations = [], helpers}: IReqTrapperConstructor = {}) {\n this.customValidations = customValidations;\n this.helpers = helpers!;\n this.errors = {}; // reset errors\n }\n\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n this.req = req;\n this.requestBody = req.body;\n this.res = res;\n this.next = next;\n\n\n\n this.rules.forEach((rule) => this.handleValidation(rule));\n console.log(this.errors)\n if (Object.keys(this.errors).length > 0) {\n res.status(400).json({ errors: this.errors });\n } else {\n\n next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n setCustomMessages(messages: { [key: string]: string }) {\n this.customMessages = messages;\n }\n\n validate(rulesArray: RuleSet[]) {\n const instance = new ReqTrapper({customValidations: this.customValidations, helpers: new Helpers()});\n instance.setRules(rulesArray);\n return instance.middleware;\n }\n\n // TODO: Add to error message\n // addValidation(name: string, callback: (value: string) => any) {\n // this.customValidations.push({\n // validation: name,\n // action: callback,\n // });\n // }\n\n private handleValidation(rule: RuleSet) {\n const value = this.requestBody?.[rule?.name];\n const validations = this.explodeValidation(rule?.validation);\n\n for (let validation of validations) {\n const [validationName, attribute] = validation.split(\":\");\n const valid = this.isValid(value, validationName, attribute);\n\n if (!valid) {\n this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);\n break;\n }\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any): boolean {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"email\":\n return this.helpers.isEmail(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in\":\n return this.helpers.isInArray(value, attribute);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"greater_than\":\n return this.helpers.isGreaterThanNum(value, attribute);\n case \"nullable\":\n return true;\n case \"url\":\n return this.helpers.isUrl(value);\n case \"boolean\":\n return this.helpers.isBoolean(value);\n case \"alpha\":\n return this.helpers.isAlpha(value);\n case \"alpha_num\":\n return this.helpers.isAlphaNum(value);\n case \"array\":\n return Array.isArray(value);\n case \"json\":\n return this.helpers.isJson(value);\n // case \"confirmed\":\n // return value === this.requestBody?.[`${rule.name}_confirmation`];\n case \"date\":\n return this.helpers.isDate(value);\n case \"after\":\n return this.helpers.isAfter(value, attribute);\n case \"before\":\n return this.helpers.isBefore(value, attribute);\n case \"unique\":\n return this.helpers.isUnique(value, attribute); // I will need to define the database check\n case \"digits\":\n return this.helpers.isDigits(value, attribute);\n case \"digits_between\":\n return this.helpers.isDigitsBetween(value, attribute);\n case \"exists\":\n return this.helpers.existsInDb(value, attribute); // I will need to define the database check\n case \"image\":\n return this.helpers.isImage(value); // Check for image types\n case \"file\":\n return this.helpers.isFile(value); // General file validation\n case \"mimes\":\n return this.helpers.isMimeType(value, attribute); // Check file MIME types\n case \"required_if\":\n return this.helpers.requiredIf(this.requestBody?.[attribute], value);\n case \"required_unless\":\n return this.helpers.requiredUnless(this.requestBody?.[attribute], value);\n case \"required_with\":\n return this.helpers.requiredWith(this.requestBody?.[attribute], value);\n case \"required_with_all\":\n return this.helpers.requiredWithAll(this.requestBody, attribute, value);\n case \"required_without\":\n return this.helpers.requiredWithout(this.requestBody?.[attribute], value);\n case \"required_without_all\":\n return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);\n default:\n const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);\n if (foundCustomValidation) {\n return foundCustomValidation.action(value, attribute) ?? false;\n }\n return false;\n }\n }\n\n private getErrorMessage(field: string, validation: string, attribute?: any) {\n const customMessageKey = `${field}.${validation}`;\n if (this.customMessages[customMessageKey]) {\n return this.customMessages[customMessageKey];\n }\n const errorMessage = (ErrorMessages?.[validation.toUpperCase()] ?? \"\")\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage || \"Validation error\";\n }\n}\n"],"mappings":"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","names":[]}

@@ -6,2 +6,3 @@ import { ReqTrapper } from './functionality/ReqTrapper.mjs';

import './interfaces/RuleSet.mjs';
import './functionality/Helpers.mjs';

@@ -8,0 +9,0 @@

@@ -6,2 +6,3 @@ import { ReqTrapper } from './functionality/ReqTrapper.js';

import './interfaces/RuleSet.js';
import './functionality/Helpers.js';

@@ -8,0 +9,0 @@

@@ -28,7 +28,32 @@ "use strict";

// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -39,52 +64,118 @@ var ErrorMessages_default = ErrorMessages;

var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
// src/functionality/ReqTrapper.ts
var ReqTrapper = class _ReqTrapper {
constructor() {
constructor({ customValidations = [], helpers } = {}) {
this.req = null;

@@ -96,30 +187,20 @@ this.res = null;

this.rules = [];
this.validations = [];
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
this.customMessages = {};
this.customValidations = [];
this.middleware = (req, res, next) => {
req && (this.req = req) && (this.requestBody = req.body);
res && (this.res = res);
next && (this.next = next);
this.rules.map((rule) => {
this.handleValidation(rule);
return;
});
const errors = { ...this.errors };
this.errors = {};
if (Object.keys(errors)?.length > 0) {
res.status(400).json({ errors, success: false, data: null });
this.req = req;
this.requestBody = req.body;
this.res = res;
this.next = next;
this.rules.forEach((rule) => this.handleValidation(rule));
console.log(this.errors);
if (Object.keys(this.errors).length > 0) {
res.status(400).json({ errors: this.errors });
} else {
this.next && this.next();
next();
}
};
this.helpers = new Helpers_default({ validations: null });
this.customValidations = customValidations;
this.helpers = helpers;
this.errors = {};
}

@@ -133,29 +214,27 @@ setRules(rulesArray) {

}
// Helps with multi requests usage
setCustomMessages(messages) {
this.customMessages = messages;
}
validate(rulesArray) {
const newInstance = new _ReqTrapper();
newInstance.setRules(rulesArray);
return newInstance.middleware;
const instance = new _ReqTrapper({ customValidations: this.customValidations, helpers: new Helpers() });
instance.setRules(rulesArray);
return instance.middleware;
}
// TODO: Add to error message
// addValidation(name: string, callback: (value: string) => any) {
// this.customValidations.push({
// validation: name,
// action: callback,
// });
// }
handleValidation(rule) {
try {
console.log("ln 78 /n", this.errors);
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
this.helpers = new Helpers_default({ validations });
for (let validation of validations) {
const attribute = validation?.split(":")?.[1];
validation = validation?.split(":")?.[0];
if (!this.isValid(value, validation, attribute)) {
this.errors[rule?.name] = this.outputError(
rule?.name,
validation,
attribute
);
break;
}
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
for (let validation of validations) {
const [validationName, attribute] = validation.split(":");
const valid = this.isValid(value, validationName, attribute);
if (!valid) {
this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);
break;
}
} catch (e) {
console.error(e);
return e;
}

@@ -170,4 +249,4 @@ }

return this.helpers.exists(value);
case "number":
return this.helpers.isNumber(value);
case "email":
return this.helpers.isEmail(value);
case "min":

@@ -177,13 +256,69 @@ return this.helpers.minimumOf(value, attribute);

return this.helpers.maximumOf(value, attribute);
case "in_array":
case "in":
return this.helpers.isInArray(value, attribute);
case "number":
return this.helpers.isNumber(value);
case "greater_than":
return this.helpers.isGreaterThanNum(value, attribute);
case "nullable":
return true;
case "url":
return this.helpers.isUrl(value);
case "boolean":
return this.helpers.isBoolean(value);
case "alpha":
return this.helpers.isAlpha(value);
case "alpha_num":
return this.helpers.isAlphaNum(value);
case "array":
return Array.isArray(value);
case "json":
return this.helpers.isJson(value);
case "date":
return this.helpers.isDate(value);
case "after":
return this.helpers.isAfter(value, attribute);
case "before":
return this.helpers.isBefore(value, attribute);
case "unique":
return this.helpers.isUnique(value, attribute);
case "digits":
return this.helpers.isDigits(value, attribute);
case "digits_between":
return this.helpers.isDigitsBetween(value, attribute);
case "exists":
return this.helpers.existsInDb(value, attribute);
case "image":
return this.helpers.isImage(value);
case "file":
return this.helpers.isFile(value);
case "mimes":
return this.helpers.isMimeType(value, attribute);
case "required_if":
return this.helpers.requiredIf(this.requestBody?.[attribute], value);
case "required_unless":
return this.helpers.requiredUnless(this.requestBody?.[attribute], value);
case "required_with":
return this.helpers.requiredWith(this.requestBody?.[attribute], value);
case "required_with_all":
return this.helpers.requiredWithAll(this.requestBody, attribute, value);
case "required_without":
return this.helpers.requiredWithout(this.requestBody?.[attribute], value);
case "required_without_all":
return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);
default:
const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);
if (foundCustomValidation) {
return foundCustomValidation.action(value, attribute) ?? false;
}
return false;
}
}
outputError(field, validation, attribute) {
const errorMessage = ErrorMessages_default?.[validation.toUpperCase()].replace(":field", field).replace(":attribute", attribute);
return errorMessage ?? "Error message not yet defined";
getErrorMessage(field, validation, attribute) {
const customMessageKey = `${field}.${validation}`;
if (this.customMessages[customMessageKey]) {
return this.customMessages[customMessageKey];
}
const errorMessage = (ErrorMessages_default?.[validation.toUpperCase()] ?? "").replace(":field", field).replace(":attribute", attribute);
return errorMessage || "Validation error";
}

@@ -190,0 +325,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts"],"sourcesContent":["import {ReqTrapper} from \"./functionality/ReqTrapper\"\nexport default ReqTrapper;","const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;","class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers","import {NextFunction, Request, Response} from \"express\";\nimport {RuleSet} from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers, {IHelpers} from \"./Helpers\";\n\n// @Todo Allow custom validation\n// @Todo Add in more validations\n// Todo - Create means to skip validation if required is not set - @Done\n\n/**\n @classdesc Main class for request trapper.\n This class is what initiates the whole process. More like the engine.\n * @member req\n * @member res\n * @member next\n * @member errors\n * @member rules\n * @member helpers\n */\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: {[key: string]: any} = {};\n private rules: RuleSet[] = [];\n private validations: string[] = [];\n private helpers: Helpers;\n\n constructor() {\n this.helpers = new Helpers({validations: null})\n }\n\n /**\n\n ## The middleware\n This handles the request\n\n @param req Express Request\n @param res Express Response\n @param next Express NextFunction\n @returns void\n */\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n req && (this.req = req) && (this.requestBody = req.body);\n res && (this.res = res);\n next && (this.next = next);\n\n this.rules.map((rule: RuleSet) => {\n this.handleValidation(rule);\n return;\n });\n const errors = {...this.errors}\n this.errors = {};\n if (Object.keys(errors)?.length > 0) {\n res.status(400).json({errors, success: false, data: null});\n } else {\n this.next && this.next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n // Helps with multi requests usage\n validate(rulesArray: RuleSet[]) {\n const newInstance = new ReqTrapper();\n newInstance.setRules(rulesArray);\n return newInstance.middleware;\n }\n\n private handleValidation(rule: RuleSet) {\n try {\n console.log(\"ln 78 /n\",this.errors);\n const value = this.requestBody?.[rule?.name];\n\n const validations = this.explodeValidation(rule?.validation);\n this.helpers = new Helpers({validations})\n\n for (let validation of validations) {\n const attribute = validation?.split(\":\")?.[1];\n validation = validation?.split(\":\")?.[0];\n if (!this.isValid(value, validation, attribute)) {\n this.errors[rule?.name] = this.outputError(\n rule?.name,\n validation,\n attribute,\n );\n break; // break out of for loop\n }\n }\n\n } catch (e) {\n console.error(e)\n return e;\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any) {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in_array\":\n return this.helpers.isInArray(value, attribute);\n case \"nullable\":\n return true;\n default:\n return false;\n }\n }\n\n private outputError(\n field: string,\n validation: string,\n attribute?: string | number,\n ) {\n const errorMessage = ErrorMessages?.[validation.toUpperCase()]\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage ?? \"Error message not yet defined\";\n }\n\n\n\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/index.ts","../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts"],"sourcesContent":["import {ReqTrapper} from \"./functionality/ReqTrapper\"\nexport default ReqTrapper;","const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;","export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}","import { NextFunction, Request, Response } from \"express\";\nimport { RuleSet } from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers from \"./Helpers\";\n\ntype TCustomValidation = {\n action: (value: string, args?: any) => any,\n validation: string\n};\n\ninterface IReqTrapperConstructor {\n customValidations?: TCustomValidation[],\n helpers?: Helpers\n}\n\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: { [key: string]: any } = {};\n private rules: RuleSet[] = [];\n private customMessages: { [key: string]: string } = {};\n private readonly customValidations: TCustomValidation[] = [];\n private helpers: Helpers;\n\n constructor({customValidations = [], helpers}: IReqTrapperConstructor = {}) {\n this.customValidations = customValidations;\n this.helpers = helpers!;\n this.errors = {}; // reset errors\n }\n\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n this.req = req;\n this.requestBody = req.body;\n this.res = res;\n this.next = next;\n\n\n\n this.rules.forEach((rule) => this.handleValidation(rule));\n console.log(this.errors)\n if (Object.keys(this.errors).length > 0) {\n res.status(400).json({ errors: this.errors });\n } else {\n\n next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n setCustomMessages(messages: { [key: string]: string }) {\n this.customMessages = messages;\n }\n\n validate(rulesArray: RuleSet[]) {\n const instance = new ReqTrapper({customValidations: this.customValidations, helpers: new Helpers()});\n instance.setRules(rulesArray);\n return instance.middleware;\n }\n\n // TODO: Add to error message\n // addValidation(name: string, callback: (value: string) => any) {\n // this.customValidations.push({\n // validation: name,\n // action: callback,\n // });\n // }\n\n private handleValidation(rule: RuleSet) {\n const value = this.requestBody?.[rule?.name];\n const validations = this.explodeValidation(rule?.validation);\n\n for (let validation of validations) {\n const [validationName, attribute] = validation.split(\":\");\n const valid = this.isValid(value, validationName, attribute);\n\n if (!valid) {\n this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);\n break;\n }\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any): boolean {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"email\":\n return this.helpers.isEmail(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in\":\n return this.helpers.isInArray(value, attribute);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"greater_than\":\n return this.helpers.isGreaterThanNum(value, attribute);\n case \"nullable\":\n return true;\n case \"url\":\n return this.helpers.isUrl(value);\n case \"boolean\":\n return this.helpers.isBoolean(value);\n case \"alpha\":\n return this.helpers.isAlpha(value);\n case \"alpha_num\":\n return this.helpers.isAlphaNum(value);\n case \"array\":\n return Array.isArray(value);\n case \"json\":\n return this.helpers.isJson(value);\n // case \"confirmed\":\n // return value === this.requestBody?.[`${rule.name}_confirmation`];\n case \"date\":\n return this.helpers.isDate(value);\n case \"after\":\n return this.helpers.isAfter(value, attribute);\n case \"before\":\n return this.helpers.isBefore(value, attribute);\n case \"unique\":\n return this.helpers.isUnique(value, attribute); // I will need to define the database check\n case \"digits\":\n return this.helpers.isDigits(value, attribute);\n case \"digits_between\":\n return this.helpers.isDigitsBetween(value, attribute);\n case \"exists\":\n return this.helpers.existsInDb(value, attribute); // I will need to define the database check\n case \"image\":\n return this.helpers.isImage(value); // Check for image types\n case \"file\":\n return this.helpers.isFile(value); // General file validation\n case \"mimes\":\n return this.helpers.isMimeType(value, attribute); // Check file MIME types\n case \"required_if\":\n return this.helpers.requiredIf(this.requestBody?.[attribute], value);\n case \"required_unless\":\n return this.helpers.requiredUnless(this.requestBody?.[attribute], value);\n case \"required_with\":\n return this.helpers.requiredWith(this.requestBody?.[attribute], value);\n case \"required_with_all\":\n return this.helpers.requiredWithAll(this.requestBody, attribute, value);\n case \"required_without\":\n return this.helpers.requiredWithout(this.requestBody?.[attribute], value);\n case \"required_without_all\":\n return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);\n default:\n const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);\n if (foundCustomValidation) {\n return foundCustomValidation.action(value, attribute) ?? false;\n }\n return false;\n }\n }\n\n private getErrorMessage(field: string, validation: string, attribute?: any) {\n const customMessageKey = `${field}.${validation}`;\n if (this.customMessages[customMessageKey]) {\n return this.customMessages[customMessageKey];\n }\n const errorMessage = (ErrorMessages?.[validation.toUpperCase()] ?? \"\")\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage || \"Validation error\";\n }\n}\n"],"mappings":"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","names":[]}
// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -12,52 +37,118 @@ var ErrorMessages_default = ErrorMessages;

var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
// src/functionality/ReqTrapper.ts
var ReqTrapper = class _ReqTrapper {
constructor() {
constructor({ customValidations = [], helpers } = {}) {
this.req = null;

@@ -69,30 +160,20 @@ this.res = null;

this.rules = [];
this.validations = [];
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
this.customMessages = {};
this.customValidations = [];
this.middleware = (req, res, next) => {
req && (this.req = req) && (this.requestBody = req.body);
res && (this.res = res);
next && (this.next = next);
this.rules.map((rule) => {
this.handleValidation(rule);
return;
});
const errors = { ...this.errors };
this.errors = {};
if (Object.keys(errors)?.length > 0) {
res.status(400).json({ errors, success: false, data: null });
this.req = req;
this.requestBody = req.body;
this.res = res;
this.next = next;
this.rules.forEach((rule) => this.handleValidation(rule));
console.log(this.errors);
if (Object.keys(this.errors).length > 0) {
res.status(400).json({ errors: this.errors });
} else {
this.next && this.next();
next();
}
};
this.helpers = new Helpers_default({ validations: null });
this.customValidations = customValidations;
this.helpers = helpers;
this.errors = {};
}

@@ -106,29 +187,27 @@ setRules(rulesArray) {

}
// Helps with multi requests usage
setCustomMessages(messages) {
this.customMessages = messages;
}
validate(rulesArray) {
const newInstance = new _ReqTrapper();
newInstance.setRules(rulesArray);
return newInstance.middleware;
const instance = new _ReqTrapper({ customValidations: this.customValidations, helpers: new Helpers() });
instance.setRules(rulesArray);
return instance.middleware;
}
// TODO: Add to error message
// addValidation(name: string, callback: (value: string) => any) {
// this.customValidations.push({
// validation: name,
// action: callback,
// });
// }
handleValidation(rule) {
try {
console.log("ln 78 /n", this.errors);
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
this.helpers = new Helpers_default({ validations });
for (let validation of validations) {
const attribute = validation?.split(":")?.[1];
validation = validation?.split(":")?.[0];
if (!this.isValid(value, validation, attribute)) {
this.errors[rule?.name] = this.outputError(
rule?.name,
validation,
attribute
);
break;
}
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
for (let validation of validations) {
const [validationName, attribute] = validation.split(":");
const valid = this.isValid(value, validationName, attribute);
if (!valid) {
this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);
break;
}
} catch (e) {
console.error(e);
return e;
}

@@ -143,4 +222,4 @@ }

return this.helpers.exists(value);
case "number":
return this.helpers.isNumber(value);
case "email":
return this.helpers.isEmail(value);
case "min":

@@ -150,13 +229,69 @@ return this.helpers.minimumOf(value, attribute);

return this.helpers.maximumOf(value, attribute);
case "in_array":
case "in":
return this.helpers.isInArray(value, attribute);
case "number":
return this.helpers.isNumber(value);
case "greater_than":
return this.helpers.isGreaterThanNum(value, attribute);
case "nullable":
return true;
case "url":
return this.helpers.isUrl(value);
case "boolean":
return this.helpers.isBoolean(value);
case "alpha":
return this.helpers.isAlpha(value);
case "alpha_num":
return this.helpers.isAlphaNum(value);
case "array":
return Array.isArray(value);
case "json":
return this.helpers.isJson(value);
case "date":
return this.helpers.isDate(value);
case "after":
return this.helpers.isAfter(value, attribute);
case "before":
return this.helpers.isBefore(value, attribute);
case "unique":
return this.helpers.isUnique(value, attribute);
case "digits":
return this.helpers.isDigits(value, attribute);
case "digits_between":
return this.helpers.isDigitsBetween(value, attribute);
case "exists":
return this.helpers.existsInDb(value, attribute);
case "image":
return this.helpers.isImage(value);
case "file":
return this.helpers.isFile(value);
case "mimes":
return this.helpers.isMimeType(value, attribute);
case "required_if":
return this.helpers.requiredIf(this.requestBody?.[attribute], value);
case "required_unless":
return this.helpers.requiredUnless(this.requestBody?.[attribute], value);
case "required_with":
return this.helpers.requiredWith(this.requestBody?.[attribute], value);
case "required_with_all":
return this.helpers.requiredWithAll(this.requestBody, attribute, value);
case "required_without":
return this.helpers.requiredWithout(this.requestBody?.[attribute], value);
case "required_without_all":
return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);
default:
const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);
if (foundCustomValidation) {
return foundCustomValidation.action(value, attribute) ?? false;
}
return false;
}
}
outputError(field, validation, attribute) {
const errorMessage = ErrorMessages_default?.[validation.toUpperCase()].replace(":field", field).replace(":attribute", attribute);
return errorMessage ?? "Error message not yet defined";
getErrorMessage(field, validation, attribute) {
const customMessageKey = `${field}.${validation}`;
if (this.customMessages[customMessageKey]) {
return this.customMessages[customMessageKey];
}
const errorMessage = (ErrorMessages_default?.[validation.toUpperCase()] ?? "").replace(":field", field).replace(":attribute", attribute);
return errorMessage || "Validation error";
}

@@ -163,0 +298,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts","../src/index.ts"],"sourcesContent":["const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;","class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers","import {NextFunction, Request, Response} from \"express\";\nimport {RuleSet} from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers, {IHelpers} from \"./Helpers\";\n\n// @Todo Allow custom validation\n// @Todo Add in more validations\n// Todo - Create means to skip validation if required is not set - @Done\n\n/**\n @classdesc Main class for request trapper.\n This class is what initiates the whole process. More like the engine.\n * @member req\n * @member res\n * @member next\n * @member errors\n * @member rules\n * @member helpers\n */\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: {[key: string]: any} = {};\n private rules: RuleSet[] = [];\n private validations: string[] = [];\n private helpers: Helpers;\n\n constructor() {\n this.helpers = new Helpers({validations: null})\n }\n\n /**\n\n ## The middleware\n This handles the request\n\n @param req Express Request\n @param res Express Response\n @param next Express NextFunction\n @returns void\n */\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n req && (this.req = req) && (this.requestBody = req.body);\n res && (this.res = res);\n next && (this.next = next);\n\n this.rules.map((rule: RuleSet) => {\n this.handleValidation(rule);\n return;\n });\n const errors = {...this.errors}\n this.errors = {};\n if (Object.keys(errors)?.length > 0) {\n res.status(400).json({errors, success: false, data: null});\n } else {\n this.next && this.next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n // Helps with multi requests usage\n validate(rulesArray: RuleSet[]) {\n const newInstance = new ReqTrapper();\n newInstance.setRules(rulesArray);\n return newInstance.middleware;\n }\n\n private handleValidation(rule: RuleSet) {\n try {\n console.log(\"ln 78 /n\",this.errors);\n const value = this.requestBody?.[rule?.name];\n\n const validations = this.explodeValidation(rule?.validation);\n this.helpers = new Helpers({validations})\n\n for (let validation of validations) {\n const attribute = validation?.split(\":\")?.[1];\n validation = validation?.split(\":\")?.[0];\n if (!this.isValid(value, validation, attribute)) {\n this.errors[rule?.name] = this.outputError(\n rule?.name,\n validation,\n attribute,\n );\n break; // break out of for loop\n }\n }\n\n } catch (e) {\n console.error(e)\n return e;\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any) {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in_array\":\n return this.helpers.isInArray(value, attribute);\n case \"nullable\":\n return true;\n default:\n return false;\n }\n }\n\n private outputError(\n field: string,\n validation: string,\n attribute?: string | number,\n ) {\n const errorMessage = ErrorMessages?.[validation.toUpperCase()]\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage ?? \"Error message not yet defined\";\n }\n\n\n\n}\n","import {ReqTrapper} from \"./functionality/ReqTrapper\"\nexport default ReqTrapper;"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts","../src/index.ts"],"sourcesContent":["const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;","export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}","import { NextFunction, Request, Response } from \"express\";\nimport { RuleSet } from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers from \"./Helpers\";\n\ntype TCustomValidation = {\n action: (value: string, args?: any) => any,\n validation: string\n};\n\ninterface IReqTrapperConstructor {\n customValidations?: TCustomValidation[],\n helpers?: Helpers\n}\n\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: { [key: string]: any } = {};\n private rules: RuleSet[] = [];\n private customMessages: { [key: string]: string } = {};\n private readonly customValidations: TCustomValidation[] = [];\n private helpers: Helpers;\n\n constructor({customValidations = [], helpers}: IReqTrapperConstructor = {}) {\n this.customValidations = customValidations;\n this.helpers = helpers!;\n this.errors = {}; // reset errors\n }\n\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n this.req = req;\n this.requestBody = req.body;\n this.res = res;\n this.next = next;\n\n\n\n this.rules.forEach((rule) => this.handleValidation(rule));\n console.log(this.errors)\n if (Object.keys(this.errors).length > 0) {\n res.status(400).json({ errors: this.errors });\n } else {\n\n next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n setCustomMessages(messages: { [key: string]: string }) {\n this.customMessages = messages;\n }\n\n validate(rulesArray: RuleSet[]) {\n const instance = new ReqTrapper({customValidations: this.customValidations, helpers: new Helpers()});\n instance.setRules(rulesArray);\n return instance.middleware;\n }\n\n // TODO: Add to error message\n // addValidation(name: string, callback: (value: string) => any) {\n // this.customValidations.push({\n // validation: name,\n // action: callback,\n // });\n // }\n\n private handleValidation(rule: RuleSet) {\n const value = this.requestBody?.[rule?.name];\n const validations = this.explodeValidation(rule?.validation);\n\n for (let validation of validations) {\n const [validationName, attribute] = validation.split(\":\");\n const valid = this.isValid(value, validationName, attribute);\n\n if (!valid) {\n this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);\n break;\n }\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any): boolean {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"email\":\n return this.helpers.isEmail(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in\":\n return this.helpers.isInArray(value, attribute);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"greater_than\":\n return this.helpers.isGreaterThanNum(value, attribute);\n case \"nullable\":\n return true;\n case \"url\":\n return this.helpers.isUrl(value);\n case \"boolean\":\n return this.helpers.isBoolean(value);\n case \"alpha\":\n return this.helpers.isAlpha(value);\n case \"alpha_num\":\n return this.helpers.isAlphaNum(value);\n case \"array\":\n return Array.isArray(value);\n case \"json\":\n return this.helpers.isJson(value);\n // case \"confirmed\":\n // return value === this.requestBody?.[`${rule.name}_confirmation`];\n case \"date\":\n return this.helpers.isDate(value);\n case \"after\":\n return this.helpers.isAfter(value, attribute);\n case \"before\":\n return this.helpers.isBefore(value, attribute);\n case \"unique\":\n return this.helpers.isUnique(value, attribute); // I will need to define the database check\n case \"digits\":\n return this.helpers.isDigits(value, attribute);\n case \"digits_between\":\n return this.helpers.isDigitsBetween(value, attribute);\n case \"exists\":\n return this.helpers.existsInDb(value, attribute); // I will need to define the database check\n case \"image\":\n return this.helpers.isImage(value); // Check for image types\n case \"file\":\n return this.helpers.isFile(value); // General file validation\n case \"mimes\":\n return this.helpers.isMimeType(value, attribute); // Check file MIME types\n case \"required_if\":\n return this.helpers.requiredIf(this.requestBody?.[attribute], value);\n case \"required_unless\":\n return this.helpers.requiredUnless(this.requestBody?.[attribute], value);\n case \"required_with\":\n return this.helpers.requiredWith(this.requestBody?.[attribute], value);\n case \"required_with_all\":\n return this.helpers.requiredWithAll(this.requestBody, attribute, value);\n case \"required_without\":\n return this.helpers.requiredWithout(this.requestBody?.[attribute], value);\n case \"required_without_all\":\n return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);\n default:\n const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);\n if (foundCustomValidation) {\n return foundCustomValidation.action(value, attribute) ?? false;\n }\n return false;\n }\n }\n\n private getErrorMessage(field: string, validation: string, attribute?: any) {\n const customMessageKey = `${field}.${validation}`;\n if (this.customMessages[customMessageKey]) {\n return this.customMessages[customMessageKey];\n }\n const errorMessage = (ErrorMessages?.[validation.toUpperCase()] ?? \"\")\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage || \"Validation error\";\n }\n}\n","import {ReqTrapper} from \"./functionality/ReqTrapper\"\nexport default ReqTrapper;"],"mappings":"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","names":[]}

@@ -29,7 +29,32 @@ "use strict";

// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -40,52 +65,118 @@ var ErrorMessages_default = ErrorMessages;

var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
// src/functionality/ReqTrapper.ts
var ReqTrapper = class _ReqTrapper {
constructor() {
constructor({ customValidations = [], helpers } = {}) {
this.req = null;

@@ -97,30 +188,20 @@ this.res = null;

this.rules = [];
this.validations = [];
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
this.customMessages = {};
this.customValidations = [];
this.middleware = (req, res, next) => {
req && (this.req = req) && (this.requestBody = req.body);
res && (this.res = res);
next && (this.next = next);
this.rules.map((rule) => {
this.handleValidation(rule);
return;
});
const errors = { ...this.errors };
this.errors = {};
if (Object.keys(errors)?.length > 0) {
res.status(400).json({ errors, success: false, data: null });
this.req = req;
this.requestBody = req.body;
this.res = res;
this.next = next;
this.rules.forEach((rule) => this.handleValidation(rule));
console.log(this.errors);
if (Object.keys(this.errors).length > 0) {
res.status(400).json({ errors: this.errors });
} else {
this.next && this.next();
next();
}
};
this.helpers = new Helpers_default({ validations: null });
this.customValidations = customValidations;
this.helpers = helpers;
this.errors = {};
}

@@ -134,29 +215,27 @@ setRules(rulesArray) {

}
// Helps with multi requests usage
setCustomMessages(messages) {
this.customMessages = messages;
}
validate(rulesArray) {
const newInstance = new _ReqTrapper();
newInstance.setRules(rulesArray);
return newInstance.middleware;
const instance = new _ReqTrapper({ customValidations: this.customValidations, helpers: new Helpers() });
instance.setRules(rulesArray);
return instance.middleware;
}
// TODO: Add to error message
// addValidation(name: string, callback: (value: string) => any) {
// this.customValidations.push({
// validation: name,
// action: callback,
// });
// }
handleValidation(rule) {
try {
console.log("ln 78 /n", this.errors);
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
this.helpers = new Helpers_default({ validations });
for (let validation of validations) {
const attribute = validation?.split(":")?.[1];
validation = validation?.split(":")?.[0];
if (!this.isValid(value, validation, attribute)) {
this.errors[rule?.name] = this.outputError(
rule?.name,
validation,
attribute
);
break;
}
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
for (let validation of validations) {
const [validationName, attribute] = validation.split(":");
const valid = this.isValid(value, validationName, attribute);
if (!valid) {
this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);
break;
}
} catch (e) {
console.error(e);
return e;
}

@@ -171,4 +250,4 @@ }

return this.helpers.exists(value);
case "number":
return this.helpers.isNumber(value);
case "email":
return this.helpers.isEmail(value);
case "min":

@@ -178,13 +257,69 @@ return this.helpers.minimumOf(value, attribute);

return this.helpers.maximumOf(value, attribute);
case "in_array":
case "in":
return this.helpers.isInArray(value, attribute);
case "number":
return this.helpers.isNumber(value);
case "greater_than":
return this.helpers.isGreaterThanNum(value, attribute);
case "nullable":
return true;
case "url":
return this.helpers.isUrl(value);
case "boolean":
return this.helpers.isBoolean(value);
case "alpha":
return this.helpers.isAlpha(value);
case "alpha_num":
return this.helpers.isAlphaNum(value);
case "array":
return Array.isArray(value);
case "json":
return this.helpers.isJson(value);
case "date":
return this.helpers.isDate(value);
case "after":
return this.helpers.isAfter(value, attribute);
case "before":
return this.helpers.isBefore(value, attribute);
case "unique":
return this.helpers.isUnique(value, attribute);
case "digits":
return this.helpers.isDigits(value, attribute);
case "digits_between":
return this.helpers.isDigitsBetween(value, attribute);
case "exists":
return this.helpers.existsInDb(value, attribute);
case "image":
return this.helpers.isImage(value);
case "file":
return this.helpers.isFile(value);
case "mimes":
return this.helpers.isMimeType(value, attribute);
case "required_if":
return this.helpers.requiredIf(this.requestBody?.[attribute], value);
case "required_unless":
return this.helpers.requiredUnless(this.requestBody?.[attribute], value);
case "required_with":
return this.helpers.requiredWith(this.requestBody?.[attribute], value);
case "required_with_all":
return this.helpers.requiredWithAll(this.requestBody, attribute, value);
case "required_without":
return this.helpers.requiredWithout(this.requestBody?.[attribute], value);
case "required_without_all":
return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);
default:
const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);
if (foundCustomValidation) {
return foundCustomValidation.action(value, attribute) ?? false;
}
return false;
}
}
outputError(field, validation, attribute) {
const errorMessage = ErrorMessages_default?.[validation.toUpperCase()].replace(":field", field).replace(":attribute", attribute);
return errorMessage ?? "Error message not yet defined";
getErrorMessage(field, validation, attribute) {
const customMessageKey = `${field}.${validation}`;
if (this.customMessages[customMessageKey]) {
return this.customMessages[customMessageKey];
}
const errorMessage = (ErrorMessages_default?.[validation.toUpperCase()] ?? "").replace(":field", field).replace(":attribute", attribute);
return errorMessage || "Validation error";
}

@@ -200,6 +335,6 @@ };

app.post("/test", reqTrapper.validate([
{ name: "test", validation: "required|in_array:a,b,c" },
{ name: "test2", validation: "required" }
{ name: "test", validation: "required|greater_than:3" }
// {name: 'test', validation: 'required'},
// {name: 'test2', validation: 'required'},
]), (req, res) => {
console.log("here");
res.sendStatus(200);

@@ -206,0 +341,0 @@ });

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/server.ts","../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts"],"sourcesContent":["import express from \"express\";\nimport {ReqTrapper} from \"./functionality/ReqTrapper\";\nconst reqTrapper = new ReqTrapper();\n\ntry {\n const app = express();\n app.use(express.json());\n app.use(express.urlencoded({extended: true, limit: \"1MB\"}))\n app.post('/test', reqTrapper.validate([\n {name: 'test', validation: 'required|in_array:a,b,c'},\n {name: 'test2', validation: 'required'},\n ]), (req, res) => {\n console.log(\"here\")\n res.sendStatus(200);\n })\n app.listen(1000, () => {\n console.log(\"server started\");\n })\n} catch (e) {\n console.log(\"An error occurred\")\n\n}","const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;","class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers","import {NextFunction, Request, Response} from \"express\";\nimport {RuleSet} from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers, {IHelpers} from \"./Helpers\";\n\n// @Todo Allow custom validation\n// @Todo Add in more validations\n// Todo - Create means to skip validation if required is not set - @Done\n\n/**\n @classdesc Main class for request trapper.\n This class is what initiates the whole process. More like the engine.\n * @member req\n * @member res\n * @member next\n * @member errors\n * @member rules\n * @member helpers\n */\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: {[key: string]: any} = {};\n private rules: RuleSet[] = [];\n private validations: string[] = [];\n private helpers: Helpers;\n\n constructor() {\n this.helpers = new Helpers({validations: null})\n }\n\n /**\n\n ## The middleware\n This handles the request\n\n @param req Express Request\n @param res Express Response\n @param next Express NextFunction\n @returns void\n */\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n req && (this.req = req) && (this.requestBody = req.body);\n res && (this.res = res);\n next && (this.next = next);\n\n this.rules.map((rule: RuleSet) => {\n this.handleValidation(rule);\n return;\n });\n const errors = {...this.errors}\n this.errors = {};\n if (Object.keys(errors)?.length > 0) {\n res.status(400).json({errors, success: false, data: null});\n } else {\n this.next && this.next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n // Helps with multi requests usage\n validate(rulesArray: RuleSet[]) {\n const newInstance = new ReqTrapper();\n newInstance.setRules(rulesArray);\n return newInstance.middleware;\n }\n\n private handleValidation(rule: RuleSet) {\n try {\n console.log(\"ln 78 /n\",this.errors);\n const value = this.requestBody?.[rule?.name];\n\n const validations = this.explodeValidation(rule?.validation);\n this.helpers = new Helpers({validations})\n\n for (let validation of validations) {\n const attribute = validation?.split(\":\")?.[1];\n validation = validation?.split(\":\")?.[0];\n if (!this.isValid(value, validation, attribute)) {\n this.errors[rule?.name] = this.outputError(\n rule?.name,\n validation,\n attribute,\n );\n break; // break out of for loop\n }\n }\n\n } catch (e) {\n console.error(e)\n return e;\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any) {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in_array\":\n return this.helpers.isInArray(value, attribute);\n case \"nullable\":\n return true;\n default:\n return false;\n }\n }\n\n private outputError(\n field: string,\n validation: string,\n attribute?: string | number,\n ) {\n const errorMessage = ErrorMessages?.[validation.toUpperCase()]\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage ?? \"Error message not yet defined\";\n }\n\n\n\n}\n"],"mappings":"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","names":["express"]}
{"version":3,"sources":["../src/server.ts","../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts"],"sourcesContent":["import express from \"express\";\nimport {ReqTrapper} from \"./functionality/ReqTrapper\";\nconst reqTrapper = new ReqTrapper();\n\n\ntry {\n const app = express();\n app.use(express.json());\n app.use(express.urlencoded({extended: true, limit: \"1MB\"}))\n app.post('/test', reqTrapper.validate([\n {name: 'test', validation: 'required|greater_than:3'},\n // {name: 'test', validation: 'required'},\n // {name: 'test2', validation: 'required'},\n ]), (req, res) => {\n res.sendStatus(200);\n })\n app.listen(1000, () => {\n console.log(\"server started\");\n })\n} catch (e) {\n console.log(\"An error occurred\")\n\n}","const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;","export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}","import { NextFunction, Request, Response } from \"express\";\nimport { RuleSet } from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers from \"./Helpers\";\n\ntype TCustomValidation = {\n action: (value: string, args?: any) => any,\n validation: string\n};\n\ninterface IReqTrapperConstructor {\n customValidations?: TCustomValidation[],\n helpers?: Helpers\n}\n\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: { [key: string]: any } = {};\n private rules: RuleSet[] = [];\n private customMessages: { [key: string]: string } = {};\n private readonly customValidations: TCustomValidation[] = [];\n private helpers: Helpers;\n\n constructor({customValidations = [], helpers}: IReqTrapperConstructor = {}) {\n this.customValidations = customValidations;\n this.helpers = helpers!;\n this.errors = {}; // reset errors\n }\n\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n this.req = req;\n this.requestBody = req.body;\n this.res = res;\n this.next = next;\n\n\n\n this.rules.forEach((rule) => this.handleValidation(rule));\n console.log(this.errors)\n if (Object.keys(this.errors).length > 0) {\n res.status(400).json({ errors: this.errors });\n } else {\n\n next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n setCustomMessages(messages: { [key: string]: string }) {\n this.customMessages = messages;\n }\n\n validate(rulesArray: RuleSet[]) {\n const instance = new ReqTrapper({customValidations: this.customValidations, helpers: new Helpers()});\n instance.setRules(rulesArray);\n return instance.middleware;\n }\n\n // TODO: Add to error message\n // addValidation(name: string, callback: (value: string) => any) {\n // this.customValidations.push({\n // validation: name,\n // action: callback,\n // });\n // }\n\n private handleValidation(rule: RuleSet) {\n const value = this.requestBody?.[rule?.name];\n const validations = this.explodeValidation(rule?.validation);\n\n for (let validation of validations) {\n const [validationName, attribute] = validation.split(\":\");\n const valid = this.isValid(value, validationName, attribute);\n\n if (!valid) {\n this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);\n break;\n }\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any): boolean {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"email\":\n return this.helpers.isEmail(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in\":\n return this.helpers.isInArray(value, attribute);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"greater_than\":\n return this.helpers.isGreaterThanNum(value, attribute);\n case \"nullable\":\n return true;\n case \"url\":\n return this.helpers.isUrl(value);\n case \"boolean\":\n return this.helpers.isBoolean(value);\n case \"alpha\":\n return this.helpers.isAlpha(value);\n case \"alpha_num\":\n return this.helpers.isAlphaNum(value);\n case \"array\":\n return Array.isArray(value);\n case \"json\":\n return this.helpers.isJson(value);\n // case \"confirmed\":\n // return value === this.requestBody?.[`${rule.name}_confirmation`];\n case \"date\":\n return this.helpers.isDate(value);\n case \"after\":\n return this.helpers.isAfter(value, attribute);\n case \"before\":\n return this.helpers.isBefore(value, attribute);\n case \"unique\":\n return this.helpers.isUnique(value, attribute); // I will need to define the database check\n case \"digits\":\n return this.helpers.isDigits(value, attribute);\n case \"digits_between\":\n return this.helpers.isDigitsBetween(value, attribute);\n case \"exists\":\n return this.helpers.existsInDb(value, attribute); // I will need to define the database check\n case \"image\":\n return this.helpers.isImage(value); // Check for image types\n case \"file\":\n return this.helpers.isFile(value); // General file validation\n case \"mimes\":\n return this.helpers.isMimeType(value, attribute); // Check file MIME types\n case \"required_if\":\n return this.helpers.requiredIf(this.requestBody?.[attribute], value);\n case \"required_unless\":\n return this.helpers.requiredUnless(this.requestBody?.[attribute], value);\n case \"required_with\":\n return this.helpers.requiredWith(this.requestBody?.[attribute], value);\n case \"required_with_all\":\n return this.helpers.requiredWithAll(this.requestBody, attribute, value);\n case \"required_without\":\n return this.helpers.requiredWithout(this.requestBody?.[attribute], value);\n case \"required_without_all\":\n return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);\n default:\n const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);\n if (foundCustomValidation) {\n return foundCustomValidation.action(value, attribute) ?? false;\n }\n return false;\n }\n }\n\n private getErrorMessage(field: string, validation: string, attribute?: any) {\n const customMessageKey = `${field}.${validation}`;\n if (this.customMessages[customMessageKey]) {\n return this.customMessages[customMessageKey];\n }\n const errorMessage = (ErrorMessages?.[validation.toUpperCase()] ?? \"\")\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage || \"Validation error\";\n }\n}\n"],"mappings":"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","names":["express"]}

@@ -5,7 +5,32 @@ // src/server.ts

// src/ErrorMessages.ts
var ErrorMessages = Object.freeze({
var ErrorMessages = /* @__PURE__ */ Object.create({
REQUIRED: "The :field is required",
EMAIL: "The :field must be a valid email address",
MIN: "The :field must be at least :attribute characters",
MAX: "The :field must not exceed :attribute characters",
IN: "The :field must be one of the following: :attribute",
NUMBER: "The :field must be a number",
MIN: "The :field must be at least :attribute characters",
IN_ARRAY: "The :field must be one of the following: :attribute"
GREATER_THAN: "The :field must be greater than :attribute",
URL: "The :field must be a valid URL",
BOOLEAN: "The :field must be a boolean value",
ALPHA: "The :field must contain only alphabetic characters",
ALPHA_NUM: "The :field must contain only alphanumeric characters",
ARRAY: "The :field must be an array",
JSON: "The :field must be a valid JSON string",
DATE: "The :field must be a valid date",
AFTER: "The :field must be a date after :attribute",
BEFORE: "The :field must be a date before :attribute",
UNIQUE: "The :field must be unique",
DIGITS: "The :field must be :attribute digits",
DIGITS_BETWEEN: "The :field must be between :attribute digits",
EXISTS: "The :field must exist in the database",
IMAGE: "The :field must be an image file",
FILE: "The :field must be a valid file",
MIMES: "The :field must be a file of type: :attribute",
REQUIRED_IF: "The :field is required when :attribute is present",
REQUIRED_UNLESS: "The :field is required unless :attribute is present",
REQUIRED_WITH: "The :field is required when :attribute is present",
REQUIRED_WITH_ALL: "The :field is required when all of :attribute are present",
REQUIRED_WITHOUT: "The :field is required when :attribute is not present",
REQUIRED_WITHOUT_ALL: "The :field is required when none of :attribute are present"
});

@@ -16,52 +41,118 @@ var ErrorMessages_default = ErrorMessages;

var Helpers = class {
constructor({ validations }) {
this.validations = validations;
exists(value) {
return value !== void 0 && value !== null && value !== "";
}
// This function is used to skip validation if not required and field is empty or not present
canEscapeValidation(value) {
const isRequired = this.validations.includes("required");
return !value && !isRequired;
isEmail(value) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(value).toLowerCase());
}
exists(value) {
return !!value;
minimumOf(value, min) {
if (typeof value === "string")
return value.length >= Number(min);
return value >= Number(min);
}
maximumOf(value, max) {
if (typeof value === "string")
return value.length <= Number(max);
return value <= Number(max);
}
isInArray(value, options) {
const array = options.split(",");
return array.includes(value);
}
isNumber(value) {
return Number.isInteger(+value) || this.canEscapeValidation(value);
return !isNaN(Number(value));
}
minimumOf(value, num) {
if (this.exists(value)) {
return value?.length >= num;
}
return this.canEscapeValidation(value);
isGreaterThanNum(value, minValue) {
console.log(value);
console.log(minValue);
return Number(value) > Number(minValue);
}
maximumOf(value, num) {
if (this.exists(value)) {
return value?.length <= num;
}
return this.canEscapeValidation(value);
isUrl(value) {
const re = new RegExp(
"^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$",
"i"
);
return re.test(value);
}
isInArray(value, arrayString) {
return this.exists(value) ? (() => {
return String(arrayString) ? (() => {
const array = String(arrayString).split(",");
return array.includes(value);
})() : false;
})() : this.canEscapeValidation(value);
isBoolean(value) {
return value === true || value === false || value === "true" || value === "false";
}
isGreaterThanNum(value, num) {
if (this.exists(value)) {
if (this.isNumber(value)) {
return +value > num;
} else {
return false;
}
isAlpha(value) {
return /^[A-Za-z]+$/.test(value);
}
isAlphaNum(value) {
return /^[A-Za-z0-9]+$/.test(value);
}
isArray(value) {
return Array.isArray(value);
}
isJson(value) {
try {
JSON.parse(value);
return true;
} catch (e) {
return false;
}
return this.canEscapeValidation(value);
}
isDate(value) {
return !isNaN(Date.parse(value));
}
isAfter(value, compareDate) {
return new Date(value) > new Date(compareDate);
}
isBefore(value, compareDate) {
return new Date(value) < new Date(compareDate);
}
isDigits(value, digits) {
return value.length === Number(digits);
}
isDigitsBetween(value, minMax) {
const [min, max] = minMax.split(",");
return value.length >= Number(min) && value.length <= Number(max);
}
isUnique(value, tableColumn) {
return true;
}
existsInDb(value, tableColumn) {
return true;
}
isImage(value) {
const validImageTypes = ["image/jpeg", "image/png", "image/gif"];
return validImageTypes.includes(value.mimetype);
}
isFile(value) {
return value instanceof Buffer || value instanceof File;
}
isMimeType(value, mimeTypes) {
const allowedMimeTypes = mimeTypes.split(",");
return allowedMimeTypes.includes(value.mimetype);
}
requiredIf(condition, value) {
return condition ? this.exists(value) : true;
}
requiredUnless(condition, value) {
return !condition ? this.exists(value) : true;
}
requiredWith(condition, value) {
return this.exists(condition) ? this.exists(value) : true;
}
requiredWithAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const allPresent = conditions.every((attr) => this.exists(requestBody[attr]));
return allPresent ? this.exists(value) : true;
}
requiredWithout(condition, value) {
return !this.exists(condition) ? this.exists(value) : true;
}
requiredWithoutAll(requestBody, attributes, value) {
const conditions = attributes.split(",");
const nonePresent = conditions.every((attr) => !this.exists(requestBody[attr]));
return nonePresent ? this.exists(value) : true;
}
};
var Helpers_default = Helpers;
// src/functionality/ReqTrapper.ts
var ReqTrapper = class _ReqTrapper {
constructor() {
constructor({ customValidations = [], helpers } = {}) {
this.req = null;

@@ -73,30 +164,20 @@ this.res = null;

this.rules = [];
this.validations = [];
/**
## The middleware
This handles the request
@param req Express Request
@param res Express Response
@param next Express NextFunction
@returns void
*/
this.customMessages = {};
this.customValidations = [];
this.middleware = (req, res, next) => {
req && (this.req = req) && (this.requestBody = req.body);
res && (this.res = res);
next && (this.next = next);
this.rules.map((rule) => {
this.handleValidation(rule);
return;
});
const errors = { ...this.errors };
this.errors = {};
if (Object.keys(errors)?.length > 0) {
res.status(400).json({ errors, success: false, data: null });
this.req = req;
this.requestBody = req.body;
this.res = res;
this.next = next;
this.rules.forEach((rule) => this.handleValidation(rule));
console.log(this.errors);
if (Object.keys(this.errors).length > 0) {
res.status(400).json({ errors: this.errors });
} else {
this.next && this.next();
next();
}
};
this.helpers = new Helpers_default({ validations: null });
this.customValidations = customValidations;
this.helpers = helpers;
this.errors = {};
}

@@ -110,29 +191,27 @@ setRules(rulesArray) {

}
// Helps with multi requests usage
setCustomMessages(messages) {
this.customMessages = messages;
}
validate(rulesArray) {
const newInstance = new _ReqTrapper();
newInstance.setRules(rulesArray);
return newInstance.middleware;
const instance = new _ReqTrapper({ customValidations: this.customValidations, helpers: new Helpers() });
instance.setRules(rulesArray);
return instance.middleware;
}
// TODO: Add to error message
// addValidation(name: string, callback: (value: string) => any) {
// this.customValidations.push({
// validation: name,
// action: callback,
// });
// }
handleValidation(rule) {
try {
console.log("ln 78 /n", this.errors);
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
this.helpers = new Helpers_default({ validations });
for (let validation of validations) {
const attribute = validation?.split(":")?.[1];
validation = validation?.split(":")?.[0];
if (!this.isValid(value, validation, attribute)) {
this.errors[rule?.name] = this.outputError(
rule?.name,
validation,
attribute
);
break;
}
const value = this.requestBody?.[rule?.name];
const validations = this.explodeValidation(rule?.validation);
for (let validation of validations) {
const [validationName, attribute] = validation.split(":");
const valid = this.isValid(value, validationName, attribute);
if (!valid) {
this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);
break;
}
} catch (e) {
console.error(e);
return e;
}

@@ -147,4 +226,4 @@ }

return this.helpers.exists(value);
case "number":
return this.helpers.isNumber(value);
case "email":
return this.helpers.isEmail(value);
case "min":

@@ -154,13 +233,69 @@ return this.helpers.minimumOf(value, attribute);

return this.helpers.maximumOf(value, attribute);
case "in_array":
case "in":
return this.helpers.isInArray(value, attribute);
case "number":
return this.helpers.isNumber(value);
case "greater_than":
return this.helpers.isGreaterThanNum(value, attribute);
case "nullable":
return true;
case "url":
return this.helpers.isUrl(value);
case "boolean":
return this.helpers.isBoolean(value);
case "alpha":
return this.helpers.isAlpha(value);
case "alpha_num":
return this.helpers.isAlphaNum(value);
case "array":
return Array.isArray(value);
case "json":
return this.helpers.isJson(value);
case "date":
return this.helpers.isDate(value);
case "after":
return this.helpers.isAfter(value, attribute);
case "before":
return this.helpers.isBefore(value, attribute);
case "unique":
return this.helpers.isUnique(value, attribute);
case "digits":
return this.helpers.isDigits(value, attribute);
case "digits_between":
return this.helpers.isDigitsBetween(value, attribute);
case "exists":
return this.helpers.existsInDb(value, attribute);
case "image":
return this.helpers.isImage(value);
case "file":
return this.helpers.isFile(value);
case "mimes":
return this.helpers.isMimeType(value, attribute);
case "required_if":
return this.helpers.requiredIf(this.requestBody?.[attribute], value);
case "required_unless":
return this.helpers.requiredUnless(this.requestBody?.[attribute], value);
case "required_with":
return this.helpers.requiredWith(this.requestBody?.[attribute], value);
case "required_with_all":
return this.helpers.requiredWithAll(this.requestBody, attribute, value);
case "required_without":
return this.helpers.requiredWithout(this.requestBody?.[attribute], value);
case "required_without_all":
return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);
default:
const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);
if (foundCustomValidation) {
return foundCustomValidation.action(value, attribute) ?? false;
}
return false;
}
}
outputError(field, validation, attribute) {
const errorMessage = ErrorMessages_default?.[validation.toUpperCase()].replace(":field", field).replace(":attribute", attribute);
return errorMessage ?? "Error message not yet defined";
getErrorMessage(field, validation, attribute) {
const customMessageKey = `${field}.${validation}`;
if (this.customMessages[customMessageKey]) {
return this.customMessages[customMessageKey];
}
const errorMessage = (ErrorMessages_default?.[validation.toUpperCase()] ?? "").replace(":field", field).replace(":attribute", attribute);
return errorMessage || "Validation error";
}

@@ -176,6 +311,6 @@ };

app.post("/test", reqTrapper.validate([
{ name: "test", validation: "required|in_array:a,b,c" },
{ name: "test2", validation: "required" }
{ name: "test", validation: "required|greater_than:3" }
// {name: 'test', validation: 'required'},
// {name: 'test2', validation: 'required'},
]), (req, res) => {
console.log("here");
res.sendStatus(200);

@@ -182,0 +317,0 @@ });

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/server.ts","../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts"],"sourcesContent":["import express from \"express\";\nimport {ReqTrapper} from \"./functionality/ReqTrapper\";\nconst reqTrapper = new ReqTrapper();\n\ntry {\n const app = express();\n app.use(express.json());\n app.use(express.urlencoded({extended: true, limit: \"1MB\"}))\n app.post('/test', reqTrapper.validate([\n {name: 'test', validation: 'required|in_array:a,b,c'},\n {name: 'test2', validation: 'required'},\n ]), (req, res) => {\n console.log(\"here\")\n res.sendStatus(200);\n })\n app.listen(1000, () => {\n console.log(\"server started\");\n })\n} catch (e) {\n console.log(\"An error occurred\")\n\n}","const ErrorMessages: any = Object.freeze({\n REQUIRED: 'The :field is required',\n NUMBER: 'The :field must be a number',\n MIN: 'The :field must be at least :attribute characters',\n IN_ARRAY: 'The :field must be one of the following: :attribute',\n});\n\nexport default ErrorMessages;","class Helpers implements IHelpers {\n validations: any;\n\n constructor({validations}: any) {\n this.validations = validations\n }\n\n\n // This function is used to skip validation if not required and field is empty or not present\n private canEscapeValidation(value: any) {\n const isRequired = this.validations.includes('required');\n return !value && !isRequired;\n }\n\n exists(value: any) {\n return !!value;\n }\n\n isNumber(value: any) {\n return Number.isInteger(+value) || this.canEscapeValidation(value); // The plus sign attempts to convert the string to a number\n }\n\n minimumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length >= num;\n }\n return this.canEscapeValidation(value);\n }\n\n maximumOf(value: string, num: number) {\n if (this.exists(value)) {\n return value?.length <= num;\n }\n return this.canEscapeValidation(value);\n }\n\n isInArray(value: string, arrayString: string) {\n return this.exists(value) ?\n (() => {\n return String(arrayString) ? (() => {\n const array = String(arrayString).split(\",\");\n return array.includes(value)\n })() : false\n })() : this.canEscapeValidation(value);\n }\n\n\n isGreaterThanNum(value: string | number, num: number) {\n if (this.exists(value)) {\n if (this.isNumber(value)) {\n return +value > num;\n } else {\n return false;\n }\n }\n return this.canEscapeValidation(value as any)\n }\n}\n\nexport interface IHelpers {\n // canEscapeValidation: (value: any) => boolean;\n exists: (value: any) => boolean;\n isNumber: (value: any) => boolean;\n minimumOf: (value: any, num: number) => boolean;\n maximumOf: (value: any, num: number) => boolean;\n isInArray: (value: any, arrayString: any) => boolean;\n isGreaterThanNum: (value: string | number, num: number) => boolean;\n}\n\nexport default Helpers","import {NextFunction, Request, Response} from \"express\";\nimport {RuleSet} from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers, {IHelpers} from \"./Helpers\";\n\n// @Todo Allow custom validation\n// @Todo Add in more validations\n// Todo - Create means to skip validation if required is not set - @Done\n\n/**\n @classdesc Main class for request trapper.\n This class is what initiates the whole process. More like the engine.\n * @member req\n * @member res\n * @member next\n * @member errors\n * @member rules\n * @member helpers\n */\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: {[key: string]: any} = {};\n private rules: RuleSet[] = [];\n private validations: string[] = [];\n private helpers: Helpers;\n\n constructor() {\n this.helpers = new Helpers({validations: null})\n }\n\n /**\n\n ## The middleware\n This handles the request\n\n @param req Express Request\n @param res Express Response\n @param next Express NextFunction\n @returns void\n */\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n req && (this.req = req) && (this.requestBody = req.body);\n res && (this.res = res);\n next && (this.next = next);\n\n this.rules.map((rule: RuleSet) => {\n this.handleValidation(rule);\n return;\n });\n const errors = {...this.errors}\n this.errors = {};\n if (Object.keys(errors)?.length > 0) {\n res.status(400).json({errors, success: false, data: null});\n } else {\n this.next && this.next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n // Helps with multi requests usage\n validate(rulesArray: RuleSet[]) {\n const newInstance = new ReqTrapper();\n newInstance.setRules(rulesArray);\n return newInstance.middleware;\n }\n\n private handleValidation(rule: RuleSet) {\n try {\n console.log(\"ln 78 /n\",this.errors);\n const value = this.requestBody?.[rule?.name];\n\n const validations = this.explodeValidation(rule?.validation);\n this.helpers = new Helpers({validations})\n\n for (let validation of validations) {\n const attribute = validation?.split(\":\")?.[1];\n validation = validation?.split(\":\")?.[0];\n if (!this.isValid(value, validation, attribute)) {\n this.errors[rule?.name] = this.outputError(\n rule?.name,\n validation,\n attribute,\n );\n break; // break out of for loop\n }\n }\n\n } catch (e) {\n console.error(e)\n return e;\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any) {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in_array\":\n return this.helpers.isInArray(value, attribute);\n case \"nullable\":\n return true;\n default:\n return false;\n }\n }\n\n private outputError(\n field: string,\n validation: string,\n attribute?: string | number,\n ) {\n const errorMessage = ErrorMessages?.[validation.toUpperCase()]\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage ?? \"Error message not yet defined\";\n }\n\n\n\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/server.ts","../src/ErrorMessages.ts","../src/functionality/Helpers.ts","../src/functionality/ReqTrapper.ts"],"sourcesContent":["import express from \"express\";\nimport {ReqTrapper} from \"./functionality/ReqTrapper\";\nconst reqTrapper = new ReqTrapper();\n\n\ntry {\n const app = express();\n app.use(express.json());\n app.use(express.urlencoded({extended: true, limit: \"1MB\"}))\n app.post('/test', reqTrapper.validate([\n {name: 'test', validation: 'required|greater_than:3'},\n // {name: 'test', validation: 'required'},\n // {name: 'test2', validation: 'required'},\n ]), (req, res) => {\n res.sendStatus(200);\n })\n app.listen(1000, () => {\n console.log(\"server started\");\n })\n} catch (e) {\n console.log(\"An error occurred\")\n\n}","const ErrorMessages: any = Object.create({\n REQUIRED: 'The :field is required',\n EMAIL: 'The :field must be a valid email address',\n MIN: 'The :field must be at least :attribute characters',\n MAX: 'The :field must not exceed :attribute characters',\n IN: 'The :field must be one of the following: :attribute',\n NUMBER: 'The :field must be a number',\n GREATER_THAN: 'The :field must be greater than :attribute',\n URL: 'The :field must be a valid URL',\n BOOLEAN: 'The :field must be a boolean value',\n ALPHA: 'The :field must contain only alphabetic characters',\n ALPHA_NUM: 'The :field must contain only alphanumeric characters',\n ARRAY: 'The :field must be an array',\n JSON: 'The :field must be a valid JSON string',\n DATE: 'The :field must be a valid date',\n AFTER: 'The :field must be a date after :attribute',\n BEFORE: 'The :field must be a date before :attribute',\n UNIQUE: 'The :field must be unique',\n DIGITS: 'The :field must be :attribute digits',\n DIGITS_BETWEEN: 'The :field must be between :attribute digits',\n EXISTS: 'The :field must exist in the database',\n IMAGE: 'The :field must be an image file',\n FILE: 'The :field must be a valid file',\n MIMES: 'The :field must be a file of type: :attribute',\n REQUIRED_IF: 'The :field is required when :attribute is present',\n REQUIRED_UNLESS: 'The :field is required unless :attribute is present',\n REQUIRED_WITH: 'The :field is required when :attribute is present',\n REQUIRED_WITH_ALL: 'The :field is required when all of :attribute are present',\n REQUIRED_WITHOUT: 'The :field is required when :attribute is not present',\n REQUIRED_WITHOUT_ALL: 'The :field is required when none of :attribute are present',\n});\n\nexport default ErrorMessages;","export default class Helpers {\n exists(value: any) {\n return value !== undefined && value !== null && value !== '';\n }\n\n isEmail(value: string) {\n const re = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return re.test(String(value).toLowerCase());\n }\n\n minimumOf(value: string | number, min: string | number) {\n if (typeof value === 'string') return value.length >= Number(min)\n return value >= Number(min)\n }\n\n maximumOf(value: string | number, max: number) {\n if (typeof value === 'string') return value.length <= Number(max)\n return value <= Number(max)\n }\n\n isInArray(value: string, options: string) {\n const array = options.split(',');\n return array.includes(value);\n }\n\n isNumber(value: any) {\n return !isNaN(Number(value));\n }\n\n isGreaterThanNum(value: any, minValue: string | number) {\n console.log(value)\n console.log(minValue)\n return Number(value) > Number(minValue);\n }\n\n isUrl(value: string) {\n const re = new RegExp(\n '^(https?:\\\\/\\\\/)?' + // protocol\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // domain name\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*' + // port and path\n '(\\\\?[;&a-z\\\\d%_.~+=-]*)?' + // query string\n '(\\\\#[-a-z\\\\d_]*)?$', 'i'\n );\n return re.test(value);\n }\n\n isBoolean(value: any) {\n return value === true || value === false || value === 'true' || value === 'false';\n }\n\n isAlpha(value: string) {\n return /^[A-Za-z]+$/.test(value);\n }\n\n isAlphaNum(value: string) {\n return /^[A-Za-z0-9]+$/.test(value);\n }\n\n isArray(value: any) {\n return Array.isArray(value);\n }\n\n isJson(value: string) {\n try {\n JSON.parse(value);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n isDate(value: string) {\n return !isNaN(Date.parse(value));\n }\n\n isAfter(value: string, compareDate: string) {\n return new Date(value) > new Date(compareDate);\n }\n\n isBefore(value: string, compareDate: string) {\n return new Date(value) < new Date(compareDate);\n }\n\n isDigits(value: string, digits: string | number) {\n return value.length === Number(digits);\n }\n\n isDigitsBetween(value: string, minMax: string) {\n const [min, max] = minMax.split(',');\n return value.length >= Number(min) && value.length <= Number(max);\n }\n\n isUnique(value: string, tableColumn: string) {\n // TODO: Implement a database check here for uniqueness\n return true; // Placeholder: Return true if unique, false otherwise\n }\n\n existsInDb(value: string, tableColumn: string) {\n // TODO: Implement a database check here to see if the value exists\n return true; // Placeholder: Return true if exists, false otherwise\n }\n\n isImage(value: any) {\n // Check if the value is a valid image file type (e.g., jpg, png, gif)\n const validImageTypes = ['image/jpeg', 'image/png', 'image/gif'];\n return validImageTypes.includes(value.mimetype);\n }\n\n isFile(value: any) {\n // General file validation (e.g., check file exists and has a valid type)\n return value instanceof Buffer || value instanceof File;\n }\n\n isMimeType(value: any, mimeTypes: string) {\n const allowedMimeTypes = mimeTypes.split(',');\n return allowedMimeTypes.includes(value.mimetype);\n }\n\n requiredIf(condition: any, value: any) {\n return condition ? this.exists(value) : true;\n }\n\n requiredUnless(condition: any, value: any) {\n return !condition ? this.exists(value) : true;\n }\n\n requiredWith(condition: any, value: any) {\n return this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const allPresent = conditions.every(attr => this.exists(requestBody[attr]));\n return allPresent ? this.exists(value) : true;\n }\n\n requiredWithout(condition: any, value: any) {\n return !this.exists(condition) ? this.exists(value) : true;\n }\n\n requiredWithoutAll(requestBody: any, attributes: string, value: any) {\n const conditions = attributes.split(',');\n const nonePresent = conditions.every(attr => !this.exists(requestBody[attr]));\n return nonePresent ? this.exists(value) : true;\n }\n}","import { NextFunction, Request, Response } from \"express\";\nimport { RuleSet } from \"../interfaces\";\nimport ErrorMessages from \"../ErrorMessages\";\nimport Helpers from \"./Helpers\";\n\ntype TCustomValidation = {\n action: (value: string, args?: any) => any,\n validation: string\n};\n\ninterface IReqTrapperConstructor {\n customValidations?: TCustomValidation[],\n helpers?: Helpers\n}\n\nexport class ReqTrapper {\n private req: Request | null = null;\n private res: Response | null = null;\n private next: NextFunction | null = null;\n private requestBody: any | null = null;\n private errors: { [key: string]: any } = {};\n private rules: RuleSet[] = [];\n private customMessages: { [key: string]: string } = {};\n private readonly customValidations: TCustomValidation[] = [];\n private helpers: Helpers;\n\n constructor({customValidations = [], helpers}: IReqTrapperConstructor = {}) {\n this.customValidations = customValidations;\n this.helpers = helpers!;\n this.errors = {}; // reset errors\n }\n\n private middleware = (req: Request, res: Response, next: NextFunction) => {\n this.req = req;\n this.requestBody = req.body;\n this.res = res;\n this.next = next;\n\n\n\n this.rules.forEach((rule) => this.handleValidation(rule));\n console.log(this.errors)\n if (Object.keys(this.errors).length > 0) {\n res.status(400).json({ errors: this.errors });\n } else {\n\n next();\n }\n };\n\n setRules(rulesArray: RuleSet[]) {\n if (!Array.isArray(rulesArray)) {\n throw new Error(\"Invalid rule set passed\");\n } else {\n this.rules = rulesArray;\n }\n }\n\n setCustomMessages(messages: { [key: string]: string }) {\n this.customMessages = messages;\n }\n\n validate(rulesArray: RuleSet[]) {\n const instance = new ReqTrapper({customValidations: this.customValidations, helpers: new Helpers()});\n instance.setRules(rulesArray);\n return instance.middleware;\n }\n\n // TODO: Add to error message\n // addValidation(name: string, callback: (value: string) => any) {\n // this.customValidations.push({\n // validation: name,\n // action: callback,\n // });\n // }\n\n private handleValidation(rule: RuleSet) {\n const value = this.requestBody?.[rule?.name];\n const validations = this.explodeValidation(rule?.validation);\n\n for (let validation of validations) {\n const [validationName, attribute] = validation.split(\":\");\n const valid = this.isValid(value, validationName, attribute);\n\n if (!valid) {\n this.errors[rule?.name] = this.getErrorMessage(rule?.name, validationName, attribute);\n break;\n }\n }\n }\n\n private explodeValidation(validation: string): string[] {\n return validation?.split(\"|\") || [];\n }\n\n private isValid(value: any, validation: string, attribute?: any): boolean {\n switch (validation) {\n case \"required\":\n return this.helpers.exists(value);\n case \"email\":\n return this.helpers.isEmail(value);\n case \"min\":\n return this.helpers.minimumOf(value, attribute);\n case \"max\":\n return this.helpers.maximumOf(value, attribute);\n case \"in\":\n return this.helpers.isInArray(value, attribute);\n case \"number\":\n return this.helpers.isNumber(value);\n case \"greater_than\":\n return this.helpers.isGreaterThanNum(value, attribute);\n case \"nullable\":\n return true;\n case \"url\":\n return this.helpers.isUrl(value);\n case \"boolean\":\n return this.helpers.isBoolean(value);\n case \"alpha\":\n return this.helpers.isAlpha(value);\n case \"alpha_num\":\n return this.helpers.isAlphaNum(value);\n case \"array\":\n return Array.isArray(value);\n case \"json\":\n return this.helpers.isJson(value);\n // case \"confirmed\":\n // return value === this.requestBody?.[`${rule.name}_confirmation`];\n case \"date\":\n return this.helpers.isDate(value);\n case \"after\":\n return this.helpers.isAfter(value, attribute);\n case \"before\":\n return this.helpers.isBefore(value, attribute);\n case \"unique\":\n return this.helpers.isUnique(value, attribute); // I will need to define the database check\n case \"digits\":\n return this.helpers.isDigits(value, attribute);\n case \"digits_between\":\n return this.helpers.isDigitsBetween(value, attribute);\n case \"exists\":\n return this.helpers.existsInDb(value, attribute); // I will need to define the database check\n case \"image\":\n return this.helpers.isImage(value); // Check for image types\n case \"file\":\n return this.helpers.isFile(value); // General file validation\n case \"mimes\":\n return this.helpers.isMimeType(value, attribute); // Check file MIME types\n case \"required_if\":\n return this.helpers.requiredIf(this.requestBody?.[attribute], value);\n case \"required_unless\":\n return this.helpers.requiredUnless(this.requestBody?.[attribute], value);\n case \"required_with\":\n return this.helpers.requiredWith(this.requestBody?.[attribute], value);\n case \"required_with_all\":\n return this.helpers.requiredWithAll(this.requestBody, attribute, value);\n case \"required_without\":\n return this.helpers.requiredWithout(this.requestBody?.[attribute], value);\n case \"required_without_all\":\n return this.helpers.requiredWithoutAll(this.requestBody, attribute, value);\n default:\n const foundCustomValidation = this.customValidations.find((item) => item.validation === validation);\n if (foundCustomValidation) {\n return foundCustomValidation.action(value, attribute) ?? false;\n }\n return false;\n }\n }\n\n private getErrorMessage(field: string, validation: string, attribute?: any) {\n const customMessageKey = `${field}.${validation}`;\n if (this.customMessages[customMessageKey]) {\n return this.customMessages[customMessageKey];\n }\n const errorMessage = (ErrorMessages?.[validation.toUpperCase()] ?? \"\")\n .replace(\":field\", field)\n .replace(\":attribute\", attribute);\n return errorMessage || \"Validation error\";\n }\n}\n"],"mappings":"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","names":[]}
{
"name": "req-trapper",
"version": "1.1.00",
"version": "1.1.01",
"description": "A package to help you easily validate your request body in express js.",

@@ -8,2 +8,3 @@ "main": "./dist/index.js",

"build": "npx tsup ./src",
"dev": "npm run build && node dist/server",
"test": "echo \"Error: no test specified\" && exit 1",

@@ -10,0 +11,0 @@ "test-server": "npm run build; node dist/server"

+159
-16

@@ -0,4 +1,7 @@

Here's the full README in markdown with all the validation rules and examples, covering the complete documentation for `req-trapper`.
# req-trapper
`req-trapper` is an Express middleware for request validation inspired by Laravel request validation. It allows you to define validation rules for your API requests and ensures that incoming data in the request payload meets your specified criteria.
`req-trapper` is an Express middleware for request validation inspired by Laravel's request validation. It allows you to define validation rules for your API requests and ensures that incoming data in the request payload meets your specified criteria.

@@ -8,7 +11,18 @@ ## Features

- **Simple and Expressive:** Define validation rules for your request data with a clean and expressive syntax.
- **Middleware Integration:** Easily integrate `req-trapper` into your Express application as middleware for route-specific request validation.
- **Extensible:** Customize validation rules to suit your application's specific needs.
- **Custom Error Messages:** Override default validation error messages with custom ones tailored to your needs.
- **Extensible:** Customize validation rules to suit your application's specific needs(This is in progress)
## Documentation
1. [Installation](#installation)
2. [Usage](#usage)
1. [Basic Example](#basic-example)
3. [Validation Rules](#validation-rules)
1. [Built-In Rules](#built-in-rules)
2. [Custom Validations](#custom-validations)
3. [Custom Error Messages](#custom-error-messages)
4. [Contributing](#contributing)
5. [License](#license)
## Installation

@@ -22,5 +36,6 @@

## Usage
## Usage
### Basic Example
```javascript

@@ -33,7 +48,5 @@ import ReqTrapper from 'req-trapper';

// Use req-trapper as middleware
app.post('/example',
reqTrapper.validate([{ name: 'phone', validation: 'required|number' }]), // validation rules
reqTrapper.validate([{ name: 'phone', validation: 'required|number' }]), // Validation rules
(req, res) => {

@@ -43,5 +56,5 @@ // Your route logic here

// works across multiple requests
// Use req-trapper in another route
app.post('/example2',
reqTrapper.validate([{ name: 'email', validation: 'required|email' }]), // validation rules
reqTrapper.validate([{ name: 'email', validation: 'required|email' }]), // Validation rules
(req, res) => {

@@ -52,11 +65,141 @@ // Your route logic here

## Rules
- `required`: Ensures that the specified field exists in the request data.
- `number`: Ensures that the specified field is a number.
- `min:x` Ensures that the specified field has at least ```x``` characters. ```x``` should be a number
## Validation Rules
### Built-In Rules
Here are the built-in validation rules you can use:
**required**: Ensures that the specified field exists in the request data.
- Example: `required`
**email**: Ensures that the specified field contains a valid email address.
- Example: `email`
**min:x**: Ensures that the specified field has at least `x` characters or is greater than or equal to `x`.
- Example: `min:5`
**max:x**: Ensures that the specified field has no more than `x` characters or is less than or equal to `x`.
- Example: `max:10`
**in:values**: Ensures that the specified field is one of the given values (comma-separated).
- Example: `in:admin,user,guest`
**number**: Ensures that the specified field is a number.
- Example: `number`
**greater_than:x**: Ensures that the specified field is greater than `x`.
- Example: `greater_than:18`
**nullable**: Allows a field to be null.
- Example: `nullable`
**url**: Ensures that the specified field is a valid URL.
- Example: `url`
**boolean**: Ensures that the specified field is a boolean.
- Example: `boolean`
**alpha**: Ensures that the specified field contains only alphabetic characters.
- Example: `alpha`
**alpha_num**: Ensures that the specified field contains only alphabetic and numeric characters.
- Example: `alpha_num`
**array**: Ensures that the specified field is an array.
- Example: `array`
**json**: Ensures that the specified field is valid JSON.
- Example: `json`
**date**: Ensures that the specified field is a valid date.
- Example: `date`
**after:date**: Ensures that the specified date field is after the given date.
- Example: `after:2024-01-01`
**before:date**: Ensures that the specified date field is before the given date.
- Example: `before:2024-01-01`
**unique**: Ensures that the specified field is unique in the database (database integration required).
- Example: `unique:users,email`
**digits:x**: Ensures that the specified field contains exactly `x` digits.
- Example: `digits:10`
**digits_between:min,max**: Ensures that the specified field contains digits between the minimum and maximum values.
- Example: `digits_between:5,10`
**exists**: Ensures that the specified field exists in the database (database integration required).
- Example: `exists:users,email`
**image**: Ensures that the specified field is an image file (based on MIME type).
- Example: `image`
**file**: Ensures that the specified field is a file.
- Example: `file`
**mimes:types**: Ensures that the file is of the specified MIME type(s).
- Example: `mimes:jpeg,png`
**required_if:other_field**: Requires the field if the other field is present.
- Example: `required_if:role,admin`
**required_unless:other_field**: Requires the field unless the other field is present.
- Example: `required_unless:role,guest`
**required_with:other_field**: Requires the field if the other field is present.
- Example: `required_with:password`
**required_with_all:fields**: Requires the field if all the other fields are present.
- Example: `required_with_all:password,confirm_password`
**required_without:other_field**: Requires the field if the other field is not present.
- Example: `required_without:email`
**required_without_all:fields**: Requires the field if none of the other fields are present.
- Example: `required_without_all:email,phone`
### Custom Validations
You can define your own custom validation rules. For example:
```javascript
const customValidations = [
{
validation: 'isEven',
action: (value) => value % 2 === 0
}
];
const reqTrapper = new ReqTrapper({ customValidations });
```
You can then use your custom validation in the rules:
```javascript
app.post('/example',
reqTrapper.validate([{ name: 'number', validation: 'required|isEven' }]),
(req, res) => {
// Your route logic here
}
);
```
### Custom Error Messages
You can override the default error messages by providing custom messages:
```javascript
const reqTrapper = new ReqTrapper();
reqTrapper.setCustomMessages({
'email.required': 'Email is mandatory!',
'phone.number': 'Phone number must be a valid number.'
});
```
These custom messages will be used in place of the default ones.
## Contributing
Contributions are welcome! Feel free to open issues or submit pull requests.
## License
This project is licensed under the ISC License.
Contributions are welcome! Feel free to open issues or submit pull requests on Github.