nox-validation 1.0.7 → 1.0.9
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 -23
- 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;
|
|
@@ -190,7 +301,6 @@ const convertTypes = (field) => {
|
|
|
190
301
|
if (type !== schema_definition?.type && schema_definition?.type !== constants.types.ALIAS) {
|
|
191
302
|
array_type = schema_definition.type;
|
|
192
303
|
}
|
|
193
|
-
|
|
194
304
|
return { type, array_type, find_relations };
|
|
195
305
|
};
|
|
196
306
|
|
|
@@ -559,15 +669,18 @@ const default_fields = [
|
|
|
559
669
|
"_id",
|
|
560
670
|
];
|
|
561
671
|
|
|
562
|
-
const buildNestedStructure = (
|
|
672
|
+
const buildNestedStructure = ({
|
|
563
673
|
schemaFields,
|
|
564
674
|
allFields,
|
|
565
675
|
relations,
|
|
566
|
-
formData,
|
|
567
676
|
relational_fields,
|
|
568
677
|
isSeparatedFields,
|
|
569
|
-
apiVersion
|
|
570
|
-
|
|
678
|
+
apiVersion,
|
|
679
|
+
maxLevel,
|
|
680
|
+
currentDepthMap,
|
|
681
|
+
rootPath,
|
|
682
|
+
isRoot,
|
|
683
|
+
}) => {
|
|
571
684
|
const root = {};
|
|
572
685
|
const nodeMap = new Map();
|
|
573
686
|
|
|
@@ -577,17 +690,17 @@ const buildNestedStructure = (
|
|
|
577
690
|
const pathParts = item.path.split(".");
|
|
578
691
|
const key = pathParts.join(".");
|
|
579
692
|
|
|
693
|
+
const currentDepth = currentDepthMap.get(isRoot ? item.path : rootPath) || 0;
|
|
694
|
+
|
|
695
|
+
// if (currentDepth >= maxLevel) return;
|
|
696
|
+
|
|
580
697
|
let childFields;
|
|
581
698
|
|
|
582
|
-
const definedType =
|
|
583
|
-
|
|
699
|
+
const definedType = generateType(item, apiVersion);
|
|
700
|
+
// apiVersion === constants.API_VERSION.V1 ? convertTypesV1(item) : convertTypes(item);
|
|
584
701
|
// const isUserKey = default_fields.some((field) => item?.path?.includes(field));
|
|
585
702
|
|
|
586
|
-
if (
|
|
587
|
-
definedType.find_relations &&
|
|
588
|
-
(item?.type === constants.types.ALIAS ||
|
|
589
|
-
item?.schema_definition?.type === constants.types.ALIAS)
|
|
590
|
-
) {
|
|
703
|
+
if (definedType.find_relations && currentDepth<=maxLevel ) {
|
|
591
704
|
const relationDetail = getForeignCollectionDetails({
|
|
592
705
|
relations: relations,
|
|
593
706
|
collection: item?.schema_id,
|
|
@@ -609,15 +722,20 @@ const buildNestedStructure = (
|
|
|
609
722
|
}
|
|
610
723
|
|
|
611
724
|
if (childFields) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
725
|
+
if (!isRoot) currentDepthMap.set(rootPath, currentDepth + 1);
|
|
726
|
+
|
|
727
|
+
childFields = buildNestedStructure({
|
|
728
|
+
schemaFields: childFields,
|
|
729
|
+
allFields: allFields,
|
|
730
|
+
relations: relations,
|
|
731
|
+
relational_fields: relational_fields,
|
|
732
|
+
isSeparatedFields,
|
|
733
|
+
apiVersion,
|
|
734
|
+
maxLevel,
|
|
735
|
+
currentDepthMap,
|
|
736
|
+
rootPath: isRoot ? item.path : rootPath,
|
|
737
|
+
isRoot: false,
|
|
738
|
+
});
|
|
621
739
|
}
|
|
622
740
|
}
|
|
623
741
|
|
|
@@ -689,12 +807,17 @@ const getAllKeys = (structure) => {
|
|
|
689
807
|
|
|
690
808
|
const normalizeKey = (key) => key.replace(/\[\d+\]/g, "");
|
|
691
809
|
|
|
692
|
-
const findDisallowedKeys = (formData, structure) => {
|
|
810
|
+
const findDisallowedKeys = (formData, structure, maxLevel) => {
|
|
693
811
|
const formKeys = [];
|
|
694
812
|
generateDynamicKeys(formData, formKeys);
|
|
695
813
|
|
|
696
814
|
const validKeys = getAllKeys(structure);
|
|
697
|
-
return formKeys.filter((key) =>
|
|
815
|
+
return formKeys.filter((key) => {
|
|
816
|
+
const keyParts = normalizeKey(key).split(".");
|
|
817
|
+
const keyLevel = keyParts.length;
|
|
818
|
+
const levelParent = keyParts.slice(maxLevel - 1).join(".");
|
|
819
|
+
return !validKeys.has(normalizeKey(keyLevel > maxLevel ? levelParent : key));
|
|
820
|
+
});
|
|
698
821
|
};
|
|
699
822
|
|
|
700
823
|
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]) {
|