nox-validation 1.0.7 → 1.0.8
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/lib/helpers.js +146 -22
- package/lib/validate.js +18 -11
- package/package.json +1 -1
package/lib/helpers.js
CHANGED
|
@@ -157,6 +157,117 @@ const isEmpty = (val) => {
|
|
|
157
157
|
return false;
|
|
158
158
|
};
|
|
159
159
|
|
|
160
|
+
// field?.field_type (Possible Values => Single, Object, Array)
|
|
161
|
+
// 1. Single => Root Field Then Its Single
|
|
162
|
+
// 2. Object => Nested Field Like Inside Array Or Object
|
|
163
|
+
// 3. Array => Any Kind Of Array Array Of String, Object etc
|
|
164
|
+
|
|
165
|
+
// field?.type (Possible Values)
|
|
166
|
+
// 1. String
|
|
167
|
+
// 2. Number
|
|
168
|
+
// 3. Date
|
|
169
|
+
// 4. Buffer
|
|
170
|
+
// 5. Boolean
|
|
171
|
+
// 6. Mixed
|
|
172
|
+
// 7. ObjectId
|
|
173
|
+
// 8. Object
|
|
174
|
+
// 9. Array
|
|
175
|
+
// 10. Alias
|
|
176
|
+
|
|
177
|
+
// field?.schema_definition?.type
|
|
178
|
+
// it is used for specially when field?.type is Array, but some times both are Array Then We Have to check
|
|
179
|
+
|
|
180
|
+
// field?.meta?.interface
|
|
181
|
+
|
|
182
|
+
const generateType = (field, api) => {
|
|
183
|
+
let { type, schema_definition, meta } = field;
|
|
184
|
+
let interfaceType = meta?.interface;
|
|
185
|
+
let array_type = schema_definition?.type;
|
|
186
|
+
let fieldType = type;
|
|
187
|
+
let find_relations = false;
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
// When type and Array Type Are Same
|
|
191
|
+
if (type === schema_definition?.type) {
|
|
192
|
+
// Type And Array Type Both is Array
|
|
193
|
+
if (type === constants.types.ARRAY) {
|
|
194
|
+
array_type = constants.types.OBJECT;
|
|
195
|
+
}
|
|
196
|
+
// Todo: when both is Alias type === constants.types.ALIAS
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
switch (api) {
|
|
200
|
+
case "v1":
|
|
201
|
+
// is Relational Field
|
|
202
|
+
if (interfaceType && interfaceType !== "none") {
|
|
203
|
+
// We Need to find Relation
|
|
204
|
+
if (
|
|
205
|
+
[constants.interfaces.MANY_TO_ANY, constants.interfaces.TRANSLATIONS].includes(
|
|
206
|
+
interfaceType
|
|
207
|
+
)
|
|
208
|
+
) {
|
|
209
|
+
find_relations = true;
|
|
210
|
+
// update type and array type accordingly interface
|
|
211
|
+
if ([constants.interfaces.MANY_TO_ANY].includes(interfaceType)) {
|
|
212
|
+
fieldType = constants.types.ARRAY;
|
|
213
|
+
array_type = constants.types.OBJECT;
|
|
214
|
+
} else {
|
|
215
|
+
fieldType = constants.types.OBJECT;
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
// It is Relational Field, so we have to update type and array type accordingly interface
|
|
219
|
+
if ([constants.interfaces.MANY_TO_ONE].includes(interfaceType)) {
|
|
220
|
+
fieldType = constants.types.OBJECT_ID;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (
|
|
224
|
+
[
|
|
225
|
+
constants.interfaces.ONE_TO_MANY,
|
|
226
|
+
constants.interfaces.MANY_TO_MANY,
|
|
227
|
+
constants.interfaces.FILES,
|
|
228
|
+
].includes(interfaceType)
|
|
229
|
+
) {
|
|
230
|
+
fieldType = constants.types.ARRAY;
|
|
231
|
+
array_type = constants.types.OBJECT_ID;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
type: fieldType,
|
|
238
|
+
array_type,
|
|
239
|
+
find_relations,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
default:
|
|
243
|
+
// API V2
|
|
244
|
+
if (
|
|
245
|
+
[
|
|
246
|
+
constants.interfaces.ONE_TO_MANY,
|
|
247
|
+
constants.interfaces.MANY_TO_MANY,
|
|
248
|
+
constants.interfaces.MANY_TO_ANY,
|
|
249
|
+
constants.interfaces.MANY_TO_ONE,
|
|
250
|
+
constants.interfaces.TRANSLATIONS,
|
|
251
|
+
].includes(interfaceType)
|
|
252
|
+
) {
|
|
253
|
+
fieldType = constants.types.OBJECT;
|
|
254
|
+
array_type = null;
|
|
255
|
+
find_relations = true;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (interfaceType === constants.interfaces.FILES) {
|
|
259
|
+
fieldType = constants.types.ARRAY;
|
|
260
|
+
array_type = constants.types.OBJECT_ID;
|
|
261
|
+
find_relations = false;
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
type: fieldType,
|
|
265
|
+
array_type,
|
|
266
|
+
find_relations,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
160
271
|
const convertTypes = (field) => {
|
|
161
272
|
let { type, schema_definition, meta } = field;
|
|
162
273
|
let array_type = schema_definition?.type ?? null;
|
|
@@ -559,15 +670,18 @@ const default_fields = [
|
|
|
559
670
|
"_id",
|
|
560
671
|
];
|
|
561
672
|
|
|
562
|
-
const buildNestedStructure = (
|
|
673
|
+
const buildNestedStructure = ({
|
|
563
674
|
schemaFields,
|
|
564
675
|
allFields,
|
|
565
676
|
relations,
|
|
566
|
-
formData,
|
|
567
677
|
relational_fields,
|
|
568
678
|
isSeparatedFields,
|
|
569
|
-
apiVersion
|
|
570
|
-
|
|
679
|
+
apiVersion,
|
|
680
|
+
maxLevel,
|
|
681
|
+
currentDepthMap,
|
|
682
|
+
rootPath,
|
|
683
|
+
isRoot,
|
|
684
|
+
}) => {
|
|
571
685
|
const root = {};
|
|
572
686
|
const nodeMap = new Map();
|
|
573
687
|
|
|
@@ -577,17 +691,17 @@ const buildNestedStructure = (
|
|
|
577
691
|
const pathParts = item.path.split(".");
|
|
578
692
|
const key = pathParts.join(".");
|
|
579
693
|
|
|
694
|
+
const currentDepth = currentDepthMap.get(isRoot ? item.path : rootPath) || 0;
|
|
695
|
+
|
|
696
|
+
if (currentDepth >= maxLevel) return;
|
|
697
|
+
|
|
580
698
|
let childFields;
|
|
581
699
|
|
|
582
|
-
const definedType =
|
|
583
|
-
|
|
700
|
+
const definedType = generateType(item, apiVersion);
|
|
701
|
+
// apiVersion === constants.API_VERSION.V1 ? convertTypesV1(item) : convertTypes(item);
|
|
584
702
|
// const isUserKey = default_fields.some((field) => item?.path?.includes(field));
|
|
585
703
|
|
|
586
|
-
if (
|
|
587
|
-
definedType.find_relations &&
|
|
588
|
-
(item?.type === constants.types.ALIAS ||
|
|
589
|
-
item?.schema_definition?.type === constants.types.ALIAS)
|
|
590
|
-
) {
|
|
704
|
+
if (definedType.find_relations) {
|
|
591
705
|
const relationDetail = getForeignCollectionDetails({
|
|
592
706
|
relations: relations,
|
|
593
707
|
collection: item?.schema_id,
|
|
@@ -609,15 +723,20 @@ const buildNestedStructure = (
|
|
|
609
723
|
}
|
|
610
724
|
|
|
611
725
|
if (childFields) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
726
|
+
if (!isRoot) currentDepthMap.set(rootPath, currentDepth + 1);
|
|
727
|
+
|
|
728
|
+
childFields = buildNestedStructure({
|
|
729
|
+
schemaFields: childFields,
|
|
730
|
+
allFields: allFields,
|
|
731
|
+
relations: relations,
|
|
732
|
+
relational_fields: relational_fields,
|
|
733
|
+
isSeparatedFields,
|
|
734
|
+
apiVersion,
|
|
735
|
+
maxLevel,
|
|
736
|
+
currentDepthMap,
|
|
737
|
+
rootPath: isRoot ? item.path : rootPath,
|
|
738
|
+
isRoot: false,
|
|
739
|
+
});
|
|
621
740
|
}
|
|
622
741
|
}
|
|
623
742
|
|
|
@@ -689,12 +808,17 @@ const getAllKeys = (structure) => {
|
|
|
689
808
|
|
|
690
809
|
const normalizeKey = (key) => key.replace(/\[\d+\]/g, "");
|
|
691
810
|
|
|
692
|
-
const findDisallowedKeys = (formData, structure) => {
|
|
811
|
+
const findDisallowedKeys = (formData, structure, maxLevel) => {
|
|
693
812
|
const formKeys = [];
|
|
694
813
|
generateDynamicKeys(formData, formKeys);
|
|
695
814
|
|
|
696
815
|
const validKeys = getAllKeys(structure);
|
|
697
|
-
return formKeys.filter((key) =>
|
|
816
|
+
return formKeys.filter((key) => {
|
|
817
|
+
const keyParts = normalizeKey(key).split(".");
|
|
818
|
+
const keyLevel = keyParts.length;
|
|
819
|
+
const levelParent = keyParts.slice(maxLevel - 1).join(".");
|
|
820
|
+
return !validKeys.has(normalizeKey(keyLevel > maxLevel ? levelParent : key));
|
|
821
|
+
});
|
|
698
822
|
};
|
|
699
823
|
|
|
700
824
|
const generateFieldCompareRules = (rule) => {
|
package/lib/validate.js
CHANGED
|
@@ -7,6 +7,7 @@ const {
|
|
|
7
7
|
getValue,
|
|
8
8
|
setValue,
|
|
9
9
|
isEmpty,
|
|
10
|
+
getParentKey,
|
|
10
11
|
} = require("./helpers");
|
|
11
12
|
|
|
12
13
|
const typeChecks = {
|
|
@@ -663,6 +664,7 @@ const schema = {
|
|
|
663
664
|
},
|
|
664
665
|
apiVersion: { type: constants.types.STRING, array_type: null },
|
|
665
666
|
language: { type: constants.types.STRING, array_type: null },
|
|
667
|
+
maxLevel: { type: constants.types.NUMBER, array_type: null },
|
|
666
668
|
};
|
|
667
669
|
|
|
668
670
|
const validate = (data) => {
|
|
@@ -677,12 +679,12 @@ const validate = (data) => {
|
|
|
677
679
|
byPassKeys,
|
|
678
680
|
apiVersion,
|
|
679
681
|
language,
|
|
682
|
+
maxLevel,
|
|
680
683
|
} = data;
|
|
681
684
|
const defaultLanguage = constants.LANGUAGES.length > 0 ? constants.LANGUAGES[0] : "en"; // Replace "en" with your actual default
|
|
682
685
|
const error_messages =
|
|
683
686
|
constants.LOCALE_MESSAGES[language] ?? constants.LOCALE_MESSAGES[defaultLanguage];
|
|
684
687
|
|
|
685
|
-
|
|
686
688
|
let result = { status: true, errors: {}, data: formData };
|
|
687
689
|
|
|
688
690
|
const updateValue = (key, value) => {
|
|
@@ -833,18 +835,23 @@ const validate = (data) => {
|
|
|
833
835
|
schemaFields = fields.filter((field) => field?.schema_id?.toString() === formId?.toString());
|
|
834
836
|
}
|
|
835
837
|
|
|
838
|
+
let currentDepthMap = new Map();
|
|
839
|
+
|
|
836
840
|
const fieldOptions =
|
|
837
|
-
buildNestedStructure(
|
|
838
|
-
schemaFields || [],
|
|
839
|
-
allFields,
|
|
840
|
-
relations,
|
|
841
|
-
|
|
842
|
-
relationalFields,
|
|
841
|
+
buildNestedStructure({
|
|
842
|
+
schemaFields: schemaFields || [],
|
|
843
|
+
allFields: allFields,
|
|
844
|
+
relations: relations,
|
|
845
|
+
relational_fields: relationalFields,
|
|
843
846
|
isSeparatedFields,
|
|
844
|
-
apiVersion
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
847
|
+
apiVersion,
|
|
848
|
+
maxLevel,
|
|
849
|
+
currentDepthMap,
|
|
850
|
+
rootPath: "",
|
|
851
|
+
isRoot: true,
|
|
852
|
+
}) || [];
|
|
853
|
+
|
|
854
|
+
findDisallowedKeys(formData, fieldOptions,maxLevel).forEach((fieldPath) => {
|
|
848
855
|
if (abortEarly && !result.status) return result;
|
|
849
856
|
const fieldKey = getLastChildKey(fieldPath);
|
|
850
857
|
if (fieldKey && !result.errors[fieldPath]) {
|