nox-validation 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # Nox Validation
2
+
3
+ `nox-validation` is a powerful and flexible validation library for both client-side and server-side use. It supports nested fields, alias validation, and customizable rules, making it perfect for complex form data validation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install nox-validation
9
+ ```
10
+
11
+ ## Library Exports
12
+
13
+ ### **Validation Functions:**
14
+ - `validate` - The core function for validating data.
15
+
16
+ ### **Constants:**
17
+ - `CONSTANTS` - A collection of predefined constants (likely including data types, error messages, validation rules, etc.).
18
+
19
+ ### **Helper Functions (`HELPERS`):**
20
+ - `validateSingleField` - Validates a single field against defined rules.
21
+ - `validateType` - Performs type checks for data validation.
22
+ - `fieldsMapping` - Groups fields by `schemaId` for structured access.
23
+ - `convertTree` - Converts a flat structure into a nested tree format.
24
+ - `getValueByDynamicKey` - Retrieves a value dynamically from an object using a key path.
25
+ - `setValueByDynamicKey` - Sets a value dynamically in an object using a key path.
26
+
27
+ ## Usage
28
+
29
+
30
+ ```javascript
31
+ const { validate, helpers } = require("nox-validation");
32
+
33
+ const all_fields = []; // fields of all collection
34
+
35
+ const relations = []; // all relations data
36
+
37
+ const schema = [
38
+ {
39
+ _id: "67d2996955b853593b84a0c8",
40
+ schema_id: "67d2993655b853593b84a086",
41
+ field: "email",
42
+ field_type: "Single",
43
+ type: "String",
44
+ path: "email",
45
+ meta: {
46
+ field: "email",
47
+ interface: "input",
48
+ hidden: false,
49
+ sort: null,
50
+ required: true,
51
+ nullable: false,
52
+ validations: {
53
+ rules: [
54
+ {
55
+ rule: "matchesRegExp",
56
+ matchesRegExp: {
57
+ value: "/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/",
58
+ },
59
+ },
60
+ ],
61
+ },
62
+ readonly: false,
63
+ },
64
+ schema_definition: {
65
+ name: "email",
66
+ type: "String",
67
+ default: null,
68
+ unique: true,
69
+ },
70
+ },
71
+ {
72
+ _id: "67d2995955b853593b84a0bc",
73
+ schema_id: "67d2993655b853593b84a086",
74
+ field: "user_name",
75
+ field_type: "Single",
76
+ type: "String",
77
+ path: "user_name",
78
+ meta: {
79
+ field: "user_name",
80
+ interface: "input",
81
+ hidden: false,
82
+ sort: null,
83
+ required: true,
84
+ nullable: false,
85
+ readonly: false,
86
+ },
87
+ schema_definition: {
88
+ name: "user_name",
89
+ type: "String",
90
+ default: null,
91
+ },
92
+ },
93
+ ];
94
+
95
+ ```
96
+
97
+ #### When `isSeparatedFields` is `true`
98
+ ```javascript
99
+ const result = validate({
100
+ formData: {
101
+ user_name: "John Doe",
102
+ email: "john.doe@example.com",
103
+ },
104
+ isSeparatedFields: true,
105
+ fields: schema,
106
+ relationalFields: helpers.fieldsMapping(all_fields),
107
+ relations: relations,
108
+ formId: "67d2993655b853593b84a086",
109
+ abortEarly: false,
110
+ byPassKeys: [],
111
+ apiVersion: "v1",
112
+ });
113
+ ```
114
+
115
+ #### When `isSeparatedFields` is `false`
116
+ ```javascript
117
+ const result = validate({
118
+ formData: {
119
+ user_name: "John Doe",
120
+ email: "john.doe@example.com",
121
+ },
122
+ isSeparatedFields: false,
123
+ fields: all_fields,
124
+ relationalFields: {},
125
+ relations: relations,
126
+ formId: "67d2993655b853593b84a086",
127
+ abortEarly: false,
128
+ byPassKeys: [],
129
+ apiVersion: "v1",
130
+ });
131
+ ```
132
+
133
+ #### Output Example:
134
+ ```javascript
135
+ {
136
+ status: true, // Validation passed
137
+ error: {}, // Empty if no errors
138
+ data: {} // Validated data
139
+ }
140
+ ```
141
+
142
+ ## Parameters
143
+
144
+ ### Schema Parameter Descriptions:
145
+
146
+ #### `formData` (Object)
147
+
148
+ - Represents the primary data structure for form submission.
149
+ - Contains key-value pairs corresponding to form fields.
150
+
151
+ #### `formId` (ObjectId)
152
+
153
+ - A unique identifier for the form schema.
154
+ - Required when `isSeparatedFields` is `true`, indicating that only form-specific fields are provided.
155
+
156
+ #### `isSeparatedFields` (Boolean)
157
+
158
+ - Determines how fields are structured in the request.
159
+ - **If `true`** → Only form schema fields are included in `fields`.
160
+ - **If `false`** → All fields for a specific tenant are included. Additionally, `relationalFields` will contain `{ schema_id: [related fields] }`.
161
+
162
+ #### `relations` (Array of Objects)
163
+
164
+ - Defines the relationships between different entities.
165
+ - Contains objects specifying relation types and linked entities.
166
+
167
+ #### `fields` (Array of Objects)
168
+
169
+ - Holds the form schema fields when `isSeparatedFields` is `true`.
170
+ - If `false`, it contains all fields for the specific tenant.
171
+
172
+ #### `relationalFields` (Object)
173
+
174
+ - Maps schema IDs to their related fields.
175
+ - Used when `isSeparatedFields` is `false` to maintain relationships between schemas and related fields.
176
+
177
+ #### `abortEarly` (Boolean)
178
+
179
+ - Determines validation behavior.
180
+ - **If `true`** → Validation stops on the first error encountered.
181
+ - **If `false`** → All validation errors are collected and returned.
182
+
183
+ #### `byPassKeys` (Array of Strings)
184
+
185
+ - Contains field names that should be skipped during validation.
186
+ - Allows exclusion of specific fields from validation checks.
187
+
188
+ #### `apiVersion` (String)
189
+
190
+ - Specifies the API version (`"v1"` or `"v2"`).
191
+ - Helps in maintaining compatibility and version control.
192
+
193
+ ## Result
194
+
195
+ The `validate` function returns an object with two keys:
196
+
197
+ - `status` (_boolean_): `true` if validation passed, `false` if there were errors.
198
+ - `error` (_object_): Contains validation errors, with field paths as keys and error messages as values.
package/index.js ADDED
@@ -0,0 +1,23 @@
1
+ const { validate, validateField, typeChecks } = require("./lib/validate");
2
+ const constants = require("./lib/constant");
3
+ const {
4
+ getFieldsGroupBySchemaId,
5
+ buildNestedStructure,
6
+ getValue,
7
+ setValue,
8
+ getDefaultValues
9
+ } = require("./lib/helpers");
10
+
11
+ module.exports = {
12
+ validate,
13
+ CONSTANTS: constants,
14
+ helpers: {
15
+ validateSingleField: validateField,
16
+ validateType: typeChecks,
17
+ fieldsMapping:getFieldsGroupBySchemaId,
18
+ convertTree:buildNestedStructure,
19
+ getValueByDynamicKey:getValue,
20
+ setValueByDynamicKey:setValue,
21
+ getTreeDefaultValues:getDefaultValues
22
+ },
23
+ };
@@ -0,0 +1,165 @@
1
+ const dataTypes = Object.freeze({
2
+ STRING: "String",
3
+ ARRAY: "Array",
4
+ OBJECT: "Object",
5
+ INT: "Int",
6
+ BINARY: "Binary",
7
+ BOOLEAN: "Boolean",
8
+ CODE: "Code",
9
+ DATE: "Date",
10
+ DECIMAL128: "Decimal128",
11
+ DOUBLE: "Double",
12
+ INT32: "Int32",
13
+ INT64: "Int64",
14
+ MAX_KEY: "MaxKey",
15
+ MIN_KEY: "MinKey",
16
+ NULL: "Null",
17
+ OBJECT_ID: "ObjectId",
18
+ BSON_REGEXP: "BSONRegExp",
19
+ BSON_SYMBOL: "BSONSymbol",
20
+ TIMESTAMP: "Timestamp",
21
+ UNDEFINED: "Undefined",
22
+ BIGINT: "BigInt",
23
+ SYMBOL: "Symbol",
24
+ });
25
+
26
+ const operatorTypes = Object.freeze({
27
+ AND: "$and",
28
+ OR: "$or",
29
+ EQUAL: "$eq",
30
+ NOT_EQUAL: "$ne",
31
+ LESS_THAN: "$lt",
32
+ LESS_THAN_EQUAL: "$lte",
33
+ GREATER_THAN: "$gt",
34
+ GREATER_THAN_EQUAL: "$gte",
35
+ IN: "$in",
36
+ NOT_IN: "$nin",
37
+ EXISTS: "$exists",
38
+ TYPE: "$type",
39
+ MOD: "$mod",
40
+ ALL: "$all",
41
+ SIZE: "$size",
42
+ });
43
+
44
+ const rulesTypes = Object.freeze({
45
+ EMPTY: "empty",
46
+ NOT_EMPTY: "not_empty",
47
+ ONE_OF: "one_of",
48
+ NOT_ONE_OF: "not_one_of",
49
+ NOT_ALLOWED: "not_allow",
50
+ REGEX: "regex",
51
+ MIN: "min_length",
52
+ MAX: "max_length",
53
+ OPERATOR: "Operator",
54
+ FIELD_COMPARE: "field_compare",
55
+ RULES_COMPARE: "rules_compare",
56
+ });
57
+
58
+ const rulesMessages = Object.freeze({
59
+ EMPTY: `{field} should be empty.`,
60
+ NOT_EMPTY: `{field} should not be empty.`,
61
+ ONE_OF: `{field} should be one of the following: {value}.`,
62
+ NOT_ONE_OF: `{field} should not be one of the following: {value}.`,
63
+ REQUIRED: `{field} is required.`,
64
+ OPTIONAL: `{field} is optional.`,
65
+ NOT_NULLABLE: `{field} can not be null.`,
66
+ INVALID_TYPE: "{field} contains invalid input type. Only {type} is allowed.",
67
+ NOT_ALLOWED_FIELD: `{field} is not allowed.`,
68
+ COMPARE: `{field} does not match the expected value.`,
69
+ RULES_COMPARE: `{field} does not meet the comparison rules.`,
70
+ ALLOW: `{field} contains allowed characters only.`,
71
+ NOT_ALLOWED: `{field} contains disallowed characters.`,
72
+ REGEX_MATCH: `{field} format is invalid.`,
73
+ REGEX_START_WITH: `{field} should start with {value}.`,
74
+ REGEX_ENDS_WITH: `{field} should end with {value}.`,
75
+ REGEX_CONTAINS: `{field} should contain {value}.`,
76
+ REGEX_EXACT: `{field} should be exactly {value}.`,
77
+ REGEX_NOT_START_WITH: `{field} should not be start with {value}.`,
78
+ REGEX_NOT_ENDS_WITH: `{field} should not be ends with {value}.`,
79
+ REGEX_NOT_CONTAINS: `{field} should not contains {value}.`,
80
+ MIN_STRING: `{field} must be at least {min} characters long.`,
81
+ MAX_STRING: `{field} must be at most {max} characters long.`,
82
+ MIN_NUMBER: `{field} must be at least {min}.`,
83
+ MAX_NUMBER: `{field} must be at most {max}.`,
84
+ AND: "{field} must be any of {value}",
85
+ OR: "{field} must be any of {value}",
86
+ EQUAL: "{field} must be equal to {value}",
87
+ NOT_EQUAL: "{field} must not be equal to {value}",
88
+ LESS_THAN: "{field} must be less than {value}",
89
+ LESS_THAN_EQUAL: "{field} must be less than or equal to {value}",
90
+ GREATER_THAN: "{field} must be greater than {value}",
91
+ GREATER_THAN_EQUAL: "{field} must be greater than or equal to {value}",
92
+ IN: "{field} must be one of the following: {value}",
93
+ NOT_IN: "{field} must not contain any of these values: {value}",
94
+ EXISTS: "{field} must exist",
95
+ TYPE: "{field} must be of type {value}",
96
+ MOD: "{field} must have a remainder of {value[1]} when divided by {value[0]}",
97
+ ALL: "{field} must contain all of the following values: {value}",
98
+ SIZE: "{field} must have a size of {value}",
99
+ });
100
+
101
+ const regexTypes = Object.freeze({
102
+ MATCH: "match",
103
+ START_WITH: "start_with",
104
+ ENDS_WITH: "ends_with",
105
+ CONTAINS: "contains",
106
+ EXACT: "exact",
107
+ NOT_START_WITH: "not_start_with",
108
+ NOT_ENDS_WITH: "not_ends_with",
109
+ NOT_CONTAINS: "not_contains",
110
+ });
111
+
112
+ const fieldTypes = Object.freeze({
113
+ SINGLE: "Single",
114
+ OBJECT: "Object",
115
+ ARRAY: "Array",
116
+ });
117
+
118
+ const types = Object.freeze({
119
+ STRING: "String",
120
+ OBJECT: "Object",
121
+ ARRAY: "Array",
122
+ DATE: "Date",
123
+ NUMBER: "Number",
124
+ ALIAS: "Alias",
125
+ OBJECT_ID: "ObjectId",
126
+ BUFFER: "Buffer",
127
+ BOOLEAN: "Boolean",
128
+ MIXED: "Mixed",
129
+ DATE_TIME: "datetime",
130
+ TIME: "time",
131
+ });
132
+
133
+ const interfaces = Object.freeze({
134
+ TIMESTAMP: "timestamp",
135
+ INPUT: "input",
136
+ MANY_TO_MANY: "list-m2m",
137
+ ONE_TO_MANY: "list-o2m",
138
+ MANY_TO_ONE: "list-m2o",
139
+ MANY_TO_ANY: "list-m2a",
140
+ FILE: "file",
141
+ FILE_IMAGE: "file-image",
142
+ FILES: "files",
143
+ TRANSLATIONS: "translations",
144
+ RELATIONAL: "relational",
145
+ });
146
+
147
+ const API_VERSION = Object.freeze({
148
+ V1: "v1",
149
+ V2: "v2",
150
+ });
151
+
152
+ const API_VERSIONS = Object.freeze(Object.values(API_VERSION));
153
+
154
+ module.exports = {
155
+ dataTypes,
156
+ operatorTypes,
157
+ rulesTypes,
158
+ rulesMessages,
159
+ regexTypes,
160
+ types,
161
+ fieldTypes,
162
+ interfaces,
163
+ API_VERSIONS,
164
+ API_VERSION,
165
+ };