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 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
- apiVersion === constants.API_VERSION.V1 ? convertTypesV1(item) : convertTypes(item);
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
- childFields = buildNestedStructure(
613
- childFields,
614
- allFields,
615
- relations,
616
- formData,
617
- relational_fields,
618
- isSeparatedFields
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) => !validKeys.has(normalizeKey(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
- formData,
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
- findDisallowedKeys(formData, fieldOptions).forEach((fieldPath) => {
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]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nox-validation",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "validate dynamic schema",
5
5
  "main": "index.js",
6
6
  "scripts": {