@resistdesign/voltra 3.0.0-alpha.33 → 3.0.0-alpha.35

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.
Files changed (40) hide show
  1. package/README.md +72 -2
  2. package/api/index.js +49 -36
  3. package/app/forms/Engine.d.ts +3 -0
  4. package/app/forms/UI.d.ts +12 -2
  5. package/app/forms/core/createAutoField.d.ts +11 -3
  6. package/app/forms/core/createFormRenderer.d.ts +3 -2
  7. package/app/forms/core/mergeSuites.d.ts +3 -2
  8. package/app/forms/core/resolveSuite.d.ts +2 -1
  9. package/app/forms/core/types.d.ts +20 -9
  10. package/app/forms/types.d.ts +34 -7
  11. package/app/index.js +21 -12
  12. package/app/utils/ApplicationState.d.ts +1 -1
  13. package/build/index.js +2 -2
  14. package/{chunk-FQMZMCXU.js → chunk-BKRJZXWX.js} +1 -1
  15. package/chunk-TJFTWPXQ.js +39 -0
  16. package/{chunk-LGM75I6P.js → chunk-WTD5BBJP.js} +223 -38
  17. package/chunk-X3NHBZUT.js +1143 -0
  18. package/common/Logging/Utils.d.ts +0 -9
  19. package/common/TypeParsing/TypeInfo.d.ts +20 -0
  20. package/common/TypeParsing/Validation.d.ts +152 -22
  21. package/common/index.js +6 -7
  22. package/iac/packs/auth.d.ts +10 -4
  23. package/iac-packs/index.d.ts +1 -0
  24. package/native/forms/UI.d.ts +8 -2
  25. package/native/forms/createNativeFormRenderer.d.ts +1 -1
  26. package/native/forms/index.d.ts +16 -0
  27. package/native/forms/suite.d.ts +1 -1
  28. package/native/index.js +71 -40
  29. package/native/testing/react-native.d.ts +33 -15
  30. package/native/utils/index.d.ts +13 -1
  31. package/package.json +1 -1
  32. package/web/forms/UI.d.ts +8 -2
  33. package/web/forms/createWebFormRenderer.d.ts +1 -1
  34. package/web/forms/suite.d.ts +1 -1
  35. package/web/index.js +234 -113
  36. package/web/utils/Route.d.ts +9 -3
  37. package/web/utils/index.d.ts +1 -0
  38. package/chunk-G5CLUK4Y.js +0 -621
  39. package/chunk-IWRHGGGH.js +0 -10
  40. package/chunk-WELZGQDJ.js +0 -456
package/app/index.js CHANGED
@@ -1,8 +1,8 @@
1
- export { createEasyLayout, getEasyLayoutTemplateDetails, getPascalCaseAreaName } from '../chunk-FQMZMCXU.js';
2
- export { Route, RouteContext, RouteContextConsumer, RouteContextProvider, RouteProvider, buildHistoryPath, buildQueryString, buildRoutePath, canUseBrowserHistory, computeTrackPixels, createBrowserRouteAdapter, createHistoryBackHandler, createManualRouteAdapter, createMemoryHistory, createNativeRouteAdapter, createRouteAdapterFromHistory, createUniversalAdapter, parseHistoryPath, useRouteContext } from '../chunk-G5CLUK4Y.js';
3
- export { AutoForm, AutoFormView, computeAreaBounds, createAutoField, createFormRenderer, getFieldKind, parseTemplate, resolveSuite, useFormEngine, validateAreas } from '../chunk-WELZGQDJ.js';
1
+ export { createEasyLayout, getEasyLayoutTemplateDetails, getPascalCaseAreaName } from '../chunk-BKRJZXWX.js';
2
+ export { computeTrackPixels } from '../chunk-TJFTWPXQ.js';
3
+ export { AutoForm, AutoFormView, Route, RouteContext, RouteContextConsumer, RouteContextProvider, RouteProvider, buildHistoryPath, buildQueryString, buildRoutePath, canUseBrowserHistory, computeAreaBounds, createAutoField, createBrowserRouteAdapter, createFormRenderer, createHistoryBackHandler, createManualRouteAdapter, createMemoryHistory, createNativeRouteAdapter, createRouteAdapterFromHistory, createUniversalAdapter, defaultTranslateValidationErrorCode, getFieldKind, parseHistoryPath, parseTemplate, resolveSuite, useFormEngine, useRouteContext, validateAreas } from '../chunk-X3NHBZUT.js';
4
4
  import '../chunk-7AMEFPPP.js';
5
- import '../chunk-IWRHGGGH.js';
5
+ import '../chunk-WTD5BBJP.js';
6
6
  import { mergeStringPaths, PATH_DELIMITER } from '../chunk-GYWRAW3Y.js';
7
7
  import '../chunk-I2KLQ2HA.js';
8
8
  import { createContext, useContext, useRef, useMemo, useCallback, useState, useEffect } from 'react';
@@ -38,6 +38,8 @@ var useApplicationStateValue = (identifier) => {
38
38
  } = useContext(ApplicationStateContext);
39
39
  const appStateRef = useRef(applicationState);
40
40
  appStateRef.current = applicationState;
41
+ const modificationStateRef = useRef(modificationState);
42
+ modificationStateRef.current = modificationState;
41
43
  const modified = useMemo(
42
44
  () => getApplicationStateModified(identifier, modificationState),
43
45
  [identifier, modificationState]
@@ -49,7 +51,11 @@ var useApplicationStateValue = (identifier) => {
49
51
  const setModified = useCallback(
50
52
  (isModified) => {
51
53
  setModificationState(
52
- setApplicationStateModified(identifier, isModified, modificationState)
54
+ setApplicationStateModified(
55
+ identifier,
56
+ isModified,
57
+ modificationStateRef.current
58
+ )
53
59
  );
54
60
  },
55
61
  [identifier, setModificationState]
@@ -130,6 +136,8 @@ var ApplicationStateProvider = ({
130
136
 
131
137
  // src/app/utils/Service.ts
132
138
  var getFullUrl = (protocol, domain, basePath = "", path = "", port) => {
139
+ const normalizedProtocol = protocol.endsWith(":") ? protocol.slice(0, -1) : protocol;
140
+ const normalizedDomain = domain.replace(/\/+$/, "");
133
141
  const portString = !!port ? `:${port}` : "";
134
142
  const fullPath = mergeStringPaths(
135
143
  basePath,
@@ -139,7 +147,8 @@ var getFullUrl = (protocol, domain, basePath = "", path = "", port) => {
139
147
  false,
140
148
  false
141
149
  );
142
- return `${protocol}://${domain}${portString}${fullPath}`;
150
+ const normalizedPath = fullPath ? fullPath.startsWith(PATH_DELIMITER) ? fullPath : `${PATH_DELIMITER}${fullPath}` : "";
151
+ return `${normalizedProtocol}://${normalizedDomain}${portString}${normalizedPath}`;
143
152
  };
144
153
  var sendServiceRequest = async (config, path = "", args = []) => {
145
154
  const { protocol, domain, port, basePath = "", authorization = "" } = config;
@@ -229,7 +238,7 @@ var useApplicationStateLoader = (config) => {
229
238
  var getKeyValueWithoutError = (obj, key) => {
230
239
  try {
231
240
  return obj[key];
232
- } catch (e) {
241
+ } catch (_error) {
233
242
  return void 0;
234
243
  }
235
244
  };
@@ -240,7 +249,8 @@ var useController = (parentValue, key, onParentValueChange, isArrayIndex = false
240
249
  try {
241
250
  setValue(value2);
242
251
  if (isArrayIndex) {
243
- const newArray = [...parentValue];
252
+ const baseArray = Array.isArray(parentValue) ? parentValue : [];
253
+ const newArray = [...baseArray];
244
254
  newArray[key] = value2;
245
255
  onParentValueChange(newArray);
246
256
  } else {
@@ -249,7 +259,7 @@ var useController = (parentValue, key, onParentValueChange, isArrayIndex = false
249
259
  [key]: value2
250
260
  });
251
261
  }
252
- } catch (e) {
262
+ } catch (_error) {
253
263
  }
254
264
  },
255
265
  [parentValue, key, onParentValueChange, isArrayIndex]
@@ -257,7 +267,7 @@ var useController = (parentValue, key, onParentValueChange, isArrayIndex = false
257
267
  useEffect(() => {
258
268
  try {
259
269
  setValue(getKeyValueWithoutError(parentValue, key));
260
- } catch (e) {
270
+ } catch (_error) {
261
271
  setValue(void 0);
262
272
  }
263
273
  }, [parentValue, key]);
@@ -378,8 +388,7 @@ var useTypeInfoORMAPI = (typeInfoORMAPI) => {
378
388
  );
379
389
  const api = useMemo(() => {
380
390
  const apiBase = {};
381
- for (const aM in typeInfoORMAPI) {
382
- const methodName = aM;
391
+ for (const methodName of Object.keys(typeInfoORMAPI)) {
383
392
  apiBase[methodName] = requestHandlerFactory(
384
393
  typeInfoORMAPI,
385
394
  methodName,
@@ -60,7 +60,7 @@ export declare const getApplicationStateValue: (identifier: ApplicationStateIden
60
60
  * @param modificationState - The current modification map.
61
61
  * @returns A new modification map with the updated flag.
62
62
  * */
63
- export declare const setApplicationStateModified: (identifier: ApplicationStateIdentifier, value: boolean, modificationState: ApplicationState) => ApplicationStateModificationState;
63
+ export declare const setApplicationStateModified: (identifier: ApplicationStateIdentifier, value: boolean, modificationState: ApplicationStateModificationState) => ApplicationStateModificationState;
64
64
  /**
65
65
  * Set the stored value for an identifier.
66
66
  *
package/build/index.js CHANGED
@@ -394,7 +394,7 @@ var getTypeInfoFromPickOmitFieldFilters = (typeNameStr, typeRef, typeMap) => {
394
394
  (fieldSet) => fieldSet.filter(
395
395
  (field) => picking ? omitFieldNames.includes(field) : !omitFieldNames.includes(field)
396
396
  )
397
- ) : void 0;
397
+ ).filter((fieldSet) => fieldSet.length > 0) : void 0;
398
398
  typeInfo = {
399
399
  ...typeInfoOther,
400
400
  fields: cleanTypeInfoFields,
@@ -438,7 +438,7 @@ var getTypeInfoFromExcludeFieldFilter = (_typeNameStr, typeRef, typeMap) => {
438
438
  );
439
439
  const cleanUnionFieldSets = existingUnionFieldSets ? existingUnionFieldSets.map(
440
440
  (fieldSet) => fieldSet.filter((field) => !excludeFieldNames.includes(field))
441
- ) : void 0;
441
+ ).filter((fieldSet) => fieldSet.length > 0) : void 0;
442
442
  typeInfo = {
443
443
  ...baseTypeInfo,
444
444
  fields: cleanTypeInfoFields,
@@ -1,4 +1,4 @@
1
- import { parseTemplate, validateAreas } from './chunk-WELZGQDJ.js';
1
+ import { parseTemplate, validateAreas } from './chunk-X3NHBZUT.js';
2
2
 
3
3
  // src/app/utils/EasyLayout.tsx
4
4
  var getPascalCaseAreaName = (area) => {
@@ -0,0 +1,39 @@
1
+ // src/app/utils/easy-layout/computeTracks.ts
2
+ var computeTrackPixels = ({
3
+ tracks,
4
+ totalPx,
5
+ gapPx = 0,
6
+ paddingPx = 0
7
+ }) => {
8
+ if (!tracks.length) {
9
+ return [];
10
+ }
11
+ const gapsPx = Math.max(0, tracks.length - 1) * Math.max(0, gapPx);
12
+ const usablePx = Math.max(0, totalPx - Math.max(0, paddingPx) * 2 - gapsPx);
13
+ let fixedPx = 0;
14
+ let frTotal = 0;
15
+ for (const track of tracks) {
16
+ if (track.kind === "px") {
17
+ fixedPx += track.value;
18
+ } else if (track.kind === "pct") {
19
+ fixedPx += usablePx * track.value / 100;
20
+ } else {
21
+ frTotal += track.value;
22
+ }
23
+ }
24
+ const remainderPx = Math.max(0, usablePx - fixedPx);
25
+ return tracks.map((track) => {
26
+ if (track.kind === "px") {
27
+ return track.value;
28
+ }
29
+ if (track.kind === "pct") {
30
+ return usablePx * track.value / 100;
31
+ }
32
+ if (frTotal <= 0) {
33
+ return 0;
34
+ }
35
+ return remainderPx * track.value / frTotal;
36
+ });
37
+ };
38
+
39
+ export { computeTrackPixels };
@@ -1,5 +1,14 @@
1
1
  import { getPathString } from './chunk-GYWRAW3Y.js';
2
2
 
3
+ // src/common/TypeParsing/TypeInfo.ts
4
+ var TypeOperation = /* @__PURE__ */ ((TypeOperation2) => {
5
+ TypeOperation2["CREATE"] = "CREATE";
6
+ TypeOperation2["READ"] = "READ";
7
+ TypeOperation2["UPDATE"] = "UPDATE";
8
+ TypeOperation2["DELETE"] = "DELETE";
9
+ return TypeOperation2;
10
+ })(TypeOperation || {});
11
+
3
12
  // src/common/TypeParsing/Validation.ts
4
13
  var RelationshipValidationType = /* @__PURE__ */ ((RelationshipValidationType2) => {
5
14
  RelationshipValidationType2["INCLUDE"] = "INCLUDE";
@@ -13,8 +22,23 @@ var PRIMITIVE_ERROR_MESSAGE_CONSTANTS = {
13
22
  number: "NOT_A_NUMBER",
14
23
  boolean: "NOT_A_BOOLEAN"
15
24
  };
25
+ var DENIED_TYPE_OPERATIONS = {
26
+ CREATE: "DENIED_TYPE_OPERATION_CREATE",
27
+ READ: "DENIED_TYPE_OPERATION_READ",
28
+ UPDATE: "DENIED_TYPE_OPERATION_UPDATE",
29
+ DELETE: "DENIED_TYPE_OPERATION_DELETE"
30
+ };
16
31
  var ERROR_MESSAGE_CONSTANTS = {
17
- MISSING: "MISSING",
32
+ NONE: "NONE",
33
+ INVALID_CUSTOM_TYPE,
34
+ [PRIMITIVE_ERROR_MESSAGE_CONSTANTS.string]: PRIMITIVE_ERROR_MESSAGE_CONSTANTS.string,
35
+ [PRIMITIVE_ERROR_MESSAGE_CONSTANTS.number]: PRIMITIVE_ERROR_MESSAGE_CONSTANTS.number,
36
+ [PRIMITIVE_ERROR_MESSAGE_CONSTANTS.boolean]: PRIMITIVE_ERROR_MESSAGE_CONSTANTS.boolean,
37
+ [DENIED_TYPE_OPERATIONS.CREATE]: DENIED_TYPE_OPERATIONS.CREATE,
38
+ [DENIED_TYPE_OPERATIONS.READ]: DENIED_TYPE_OPERATIONS.READ,
39
+ [DENIED_TYPE_OPERATIONS.UPDATE]: DENIED_TYPE_OPERATIONS.UPDATE,
40
+ [DENIED_TYPE_OPERATIONS.DELETE]: DENIED_TYPE_OPERATIONS.DELETE,
41
+ MISSING_FIELD_VALUE: "MISSING_FIELD_VALUE",
18
42
  INVALID_OPTION: "INVALID_OPTION",
19
43
  INVALID_FIELD: "INVALID_FIELD",
20
44
  RELATIONSHIP_VALUES_ARE_STRICTLY_EXCLUDED: "RELATIONSHIP_VALUES_ARE_STRICTLY_EXCLUDED",
@@ -22,34 +46,61 @@ var ERROR_MESSAGE_CONSTANTS = {
22
46
  NO_UNION_TYPE_MATCHED: "NO_UNION_TYPE_MATCHED",
23
47
  TYPE_DOES_NOT_EXIST: "TYPE_DOES_NOT_EXIST",
24
48
  INVALID_PATTERN: "INVALID_PATTERN",
25
- VALUE_DOES_NOT_MATCH_PATTERN: "VALUE_DOES_NOT_MATCH_PATTERN"
49
+ VALUE_DOES_NOT_MATCH_PATTERN: "VALUE_DOES_NOT_MATCH_PATTERN",
50
+ VALUE_BELOW_MINIMUM: "VALUE_BELOW_MINIMUM",
51
+ VALUE_ABOVE_MAXIMUM: "VALUE_ABOVE_MAXIMUM"
26
52
  };
27
- var DENIED_TYPE_OPERATIONS = {
28
- CREATE: "DENIED_TYPE_OPERATION_CREATE",
29
- READ: "DENIED_TYPE_OPERATION_READ",
30
- UPDATE: "DENIED_TYPE_OPERATION_UPDATE",
31
- DELETE: "DENIED_TYPE_OPERATION_DELETE"
53
+ var TYPE_KEYWORD_ERROR_MESSAGE_CONSTANTS = {
54
+ string: PRIMITIVE_ERROR_MESSAGE_CONSTANTS.string,
55
+ number: PRIMITIVE_ERROR_MESSAGE_CONSTANTS.number,
56
+ boolean: PRIMITIVE_ERROR_MESSAGE_CONSTANTS.boolean
32
57
  };
58
+ var ARRAY_ITEM_ERROR_MAP_KEY = "__arrayItemErrors__";
59
+ var getErrorDescriptor = (code = ERROR_MESSAGE_CONSTANTS.NONE, values) => ({
60
+ code,
61
+ values
62
+ });
63
+ var getNoErrorDescriptor = () => getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.NONE);
64
+ var isArrayErrorDescriptorCollection = (value) => typeof value === "object" && value !== null && "itemErrorMap" in value;
65
+ var getErrorDescriptors = (values = []) => values.filter(
66
+ (value) => !isArrayErrorDescriptorCollection(value)
67
+ );
68
+ var getArrayItemErrorMap = (values = []) => values.reduce((acc, value) => {
69
+ if (isArrayErrorDescriptorCollection(value)) {
70
+ for (const [indexKey, descriptors] of Object.entries(value.itemErrorMap)) {
71
+ const index = Number(indexKey);
72
+ if (!Number.isFinite(index)) {
73
+ continue;
74
+ }
75
+ acc[index] = [...acc[index] ?? [], ...descriptors];
76
+ }
77
+ }
78
+ return acc;
79
+ }, {});
33
80
  var validateValueMatchesPattern = (typeName, value, pattern) => {
34
81
  const results = {
35
82
  typeName,
36
83
  valid: true,
37
- error: "",
84
+ error: getNoErrorDescriptor(),
38
85
  errorMap: {}
39
86
  };
40
87
  const valueSupplied = typeof value !== "undefined";
41
88
  const patternSupplied = typeof pattern === "string" && pattern.trim() !== "";
42
- if (!valueSupplied || !patternSupplied) {
89
+ if (valueSupplied && patternSupplied) {
43
90
  try {
44
91
  const regex = new RegExp(pattern);
45
92
  const testResult = typeof value === "string" && regex.test(value);
46
93
  if (!testResult) {
47
94
  results.valid = false;
48
- results.error = ERROR_MESSAGE_CONSTANTS.VALUE_DOES_NOT_MATCH_PATTERN;
95
+ results.error = getErrorDescriptor(
96
+ ERROR_MESSAGE_CONSTANTS.VALUE_DOES_NOT_MATCH_PATTERN
97
+ );
49
98
  }
50
99
  } catch (e) {
51
100
  results.valid = false;
52
- results.error = ERROR_MESSAGE_CONSTANTS.INVALID_PATTERN;
101
+ results.error = getErrorDescriptor(
102
+ ERROR_MESSAGE_CONSTANTS.INVALID_PATTERN
103
+ );
53
104
  }
54
105
  }
55
106
  return results;
@@ -90,23 +141,40 @@ var validateTypeInfoFieldValue = (value, typeInfoField, typeInfoMap, ignoreArray
90
141
  array,
91
142
  optional,
92
143
  possibleValues,
93
- tags: { customType, constraints: { pattern = void 0 } = {} } = {}
144
+ tags: {
145
+ customType,
146
+ validation: {
147
+ emptyArrayIsValid: emptyArrayIsValidOverride = void 0
148
+ } = {},
149
+ constraints: {
150
+ pattern = void 0,
151
+ min = void 0,
152
+ max = void 0
153
+ } = {}
154
+ } = {}
94
155
  } = typeInfoField;
95
156
  const results = {
96
157
  typeName: typeReference ?? type,
97
158
  valid: true,
98
- error: "",
159
+ error: getNoErrorDescriptor(),
99
160
  errorMap: {}
100
161
  };
101
162
  const requiredValueAllowed = !typeReference || relationshipValidationType === "INCLUDE" /* INCLUDE */;
102
163
  const valueIsUndefined = typeof value === "undefined";
103
164
  const valueIsNull = value === null;
104
165
  const canSkipValidation = itemIsPartial && (valueIsUndefined || valueIsNull) || optional && valueIsUndefined;
166
+ const emptyArrayIsValid = emptyArrayIsValidOverride ?? false;
105
167
  if (canSkipValidation) {
106
168
  results.valid = true;
107
169
  } else if (requiredValueAllowed && !itemIsPartial && !optional && !hasValue(value)) {
108
170
  results.valid = false;
109
- results.error = ERROR_MESSAGE_CONSTANTS.MISSING;
171
+ results.error = getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.MISSING_FIELD_VALUE);
172
+ } else if (array && !ignoreArray && !Array.isArray(value)) {
173
+ results.valid = false;
174
+ results.error = getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.INVALID_TYPE);
175
+ } else if (array && !ignoreArray && !optional && Array.isArray(value) && value.length === 0 && !emptyArrayIsValid) {
176
+ results.valid = false;
177
+ results.error = getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.MISSING_FIELD_VALUE);
110
178
  } else if (array && !ignoreArray) {
111
179
  const {
112
180
  valid: validArray,
@@ -149,14 +217,18 @@ var validateTypeInfoFieldValue = (value, typeInfoField, typeInfoMap, ignoreArray
149
217
  const valueSupplied = typeof value !== "undefined";
150
218
  if (valueSupplied) {
151
219
  results.valid = false;
152
- results.error = ERROR_MESSAGE_CONSTANTS.RELATIONSHIP_VALUES_ARE_STRICTLY_EXCLUDED;
220
+ results.error = getErrorDescriptor(
221
+ ERROR_MESSAGE_CONSTANTS.RELATIONSHIP_VALUES_ARE_STRICTLY_EXCLUDED
222
+ );
153
223
  }
154
224
  } else if (relationshipValidationType === "EXCLUDE" /* EXCLUDE */) {
155
225
  results.valid = getValidityValue(results.valid, true);
156
226
  }
157
227
  } else if (possibleValues && !possibleValues.includes(value)) {
158
228
  results.valid = false;
159
- results.error = ERROR_MESSAGE_CONSTANTS.INVALID_OPTION;
229
+ results.error = getErrorDescriptor(
230
+ ERROR_MESSAGE_CONSTANTS.INVALID_OPTION
231
+ );
160
232
  } else {
161
233
  const pendingValid = validateKeywordType(value, type);
162
234
  const customValid = validateCustomType(
@@ -167,14 +239,33 @@ var validateTypeInfoFieldValue = (value, typeInfoField, typeInfoMap, ignoreArray
167
239
  results.valid = getValidityValue(results.valid, pendingValid);
168
240
  results.valid = getValidityValue(results.valid, customValid);
169
241
  if (type === "string" && typeof pattern === "string") {
170
- const { valid: patternValid, error: patternError } = validateValueMatchesPattern(value, pattern);
242
+ const { valid: patternValid, error: patternError } = validateValueMatchesPattern(typeReference ?? type, value, pattern);
171
243
  results.valid = getValidityValue(results.valid, patternValid);
172
244
  results.error = patternError;
173
245
  }
246
+ if (type === "number" && typeof value === "number") {
247
+ if (typeof min === "number" && value < min) {
248
+ results.valid = false;
249
+ results.error = getErrorDescriptor(
250
+ ERROR_MESSAGE_CONSTANTS.VALUE_BELOW_MINIMUM,
251
+ [`${min}`]
252
+ );
253
+ } else if (typeof max === "number" && value > max) {
254
+ results.valid = false;
255
+ results.error = getErrorDescriptor(
256
+ ERROR_MESSAGE_CONSTANTS.VALUE_ABOVE_MAXIMUM,
257
+ [`${max}`]
258
+ );
259
+ }
260
+ }
174
261
  if (!customValid) {
175
- results.error = INVALID_CUSTOM_TYPE;
262
+ results.error = getErrorDescriptor(
263
+ ERROR_MESSAGE_CONSTANTS.INVALID_CUSTOM_TYPE
264
+ );
176
265
  } else if (!results.valid) {
177
- results.error = results.error ? results.error : PRIMITIVE_ERROR_MESSAGE_CONSTANTS[type];
266
+ results.error = results.error.code !== ERROR_MESSAGE_CONSTANTS.NONE ? results.error : getErrorDescriptor(
267
+ TYPE_KEYWORD_ERROR_MESSAGE_CONSTANTS[type]
268
+ );
178
269
  }
179
270
  }
180
271
  }
@@ -185,14 +276,15 @@ var validateArrayOfTypeInfoFieldValues = (values = [], typeInfoField, typeInfoMa
185
276
  const results = {
186
277
  typeName: typeReference ?? type,
187
278
  valid: true,
188
- error: "",
279
+ error: getNoErrorDescriptor(),
189
280
  errorMap: {}
190
281
  };
282
+ const itemErrorMap = {};
191
283
  for (let i = 0; i < values.length; i++) {
192
284
  const v = values[i];
193
285
  const {
194
286
  valid: indexValid,
195
- error: indexError = "",
287
+ error: indexError = getNoErrorDescriptor(),
196
288
  errorMap: indexErrorMap
197
289
  } = validateTypeInfoFieldValue(
198
290
  v,
@@ -206,18 +298,32 @@ var validateArrayOfTypeInfoFieldValues = (values = [], typeInfoField, typeInfoMa
206
298
  itemIsPartial
207
299
  );
208
300
  results.valid = getValidityValue(results.valid, indexValid);
209
- results.errorMap[getPathString([i])] = [indexError];
210
- for (const er in indexErrorMap) {
211
- results.errorMap[getPathString([i, er])] = indexErrorMap[er];
301
+ const indexErrors = [
302
+ ...indexError.code !== ERROR_MESSAGE_CONSTANTS.NONE ? [indexError] : [],
303
+ ...getErrorDescriptors(indexErrorMap[ARRAY_ITEM_ERROR_MAP_KEY] ?? []),
304
+ ...Object.entries(indexErrorMap).filter(([key]) => key !== ARRAY_ITEM_ERROR_MAP_KEY).flatMap(([, entries]) => getErrorDescriptors(entries)).filter((descriptor) => descriptor.code !== ERROR_MESSAGE_CONSTANTS.NONE)
305
+ ];
306
+ if (indexErrors.length) {
307
+ itemErrorMap[i] = indexErrors;
308
+ if (results.error.code === ERROR_MESSAGE_CONSTANTS.NONE) {
309
+ results.error = indexErrors[0];
310
+ }
311
+ }
312
+ for (const [er, entries] of Object.entries(indexErrorMap)) {
313
+ if (er === ARRAY_ITEM_ERROR_MAP_KEY) {
314
+ continue;
315
+ }
316
+ results.errorMap[getPathString([i, er])] = entries;
212
317
  }
213
318
  }
319
+ results.errorMap[ARRAY_ITEM_ERROR_MAP_KEY] = [{ itemErrorMap }];
214
320
  return results;
215
321
  };
216
322
  var validateTypeInfoFieldOperationAllowed = (fieldName, fieldOperation, typeInfoField) => {
217
323
  const results = {
218
324
  typeName: null,
219
325
  valid: true,
220
- error: "",
326
+ error: getNoErrorDescriptor(),
221
327
  errorMap: {}
222
328
  };
223
329
  if (fieldOperation && typeInfoField) {
@@ -230,7 +336,9 @@ var validateTypeInfoFieldOperationAllowed = (fieldName, fieldOperation, typeInfo
230
336
  results.typeName = typeReference ?? type;
231
337
  results.valid = !denied;
232
338
  if (!results.valid) {
233
- results.error = DENIED_TYPE_OPERATIONS[fieldOperation];
339
+ results.error = getErrorDescriptor(
340
+ DENIED_TYPE_OPERATIONS[fieldOperation]
341
+ );
234
342
  results.errorMap[fieldName] = [results.error];
235
343
  }
236
344
  }
@@ -240,14 +348,14 @@ var validateTypeOperationAllowed = (typeName, valueFields, typeOperation, typeIn
240
348
  const results = {
241
349
  typeName,
242
350
  valid: true,
243
- error: "",
351
+ error: getNoErrorDescriptor(),
244
352
  errorMap: {}
245
353
  };
246
354
  const { fields = {}, tags = {} } = typeInfo;
247
355
  const { deniedOperations: { [typeOperation]: denied = false } = {} } = tags;
248
356
  if (denied) {
249
357
  results.valid = false;
250
- results.error = DENIED_TYPE_OPERATIONS[typeOperation];
358
+ results.error = getErrorDescriptor(DENIED_TYPE_OPERATIONS[typeOperation]);
251
359
  } else {
252
360
  for (const vF of valueFields) {
253
361
  const vFieldInfo = fields[vF];
@@ -260,12 +368,75 @@ var validateTypeOperationAllowed = (typeName, valueFields, typeOperation, typeIn
260
368
  }
261
369
  return results;
262
370
  };
371
+ var TYPE_INFO_DATA_ITEM_TYPE_NAME = "__TYPE_INFO_DATA_ITEM__";
372
+ var validateTypeInfoDataItem = (value = {}, typeInfo, customValidatorMap = {}, options) => {
373
+ const {
374
+ typeName = TYPE_INFO_DATA_ITEM_TYPE_NAME,
375
+ typeInfoMap = {},
376
+ strict = true,
377
+ customTypeValidators,
378
+ typeOperation = "CREATE" /* CREATE */,
379
+ relationshipValidationType = "STRICT_EXCLUDE" /* STRICT_EXCLUDE */,
380
+ itemIsPartial = typeOperation === "UPDATE" /* UPDATE */,
381
+ validateHidden = false,
382
+ validateReadonly = false
383
+ } = options ?? {};
384
+ const sourceFields = typeInfo.fields ?? {};
385
+ const normalizedFields = {};
386
+ for (const [fieldName, field] of Object.entries(sourceFields)) {
387
+ const validationTags = field.tags?.validation ?? {};
388
+ const shouldValidateHidden = validationTags.validateHidden ?? validateHidden;
389
+ const shouldValidateReadonly = validationTags.validateReadonly ?? validateReadonly;
390
+ const shouldSkipRequiredChecks = field.tags?.hidden && !shouldValidateHidden || field.readonly && !shouldValidateReadonly;
391
+ normalizedFields[fieldName] = shouldSkipRequiredChecks ? {
392
+ ...field,
393
+ optional: true
394
+ } : field;
395
+ }
396
+ const normalizedTypeInfo = {
397
+ ...typeInfo,
398
+ fields: normalizedFields
399
+ };
400
+ const results = validateTypeInfoValue(
401
+ value ?? {},
402
+ typeName,
403
+ { ...typeInfoMap, [typeName]: normalizedTypeInfo },
404
+ strict,
405
+ customTypeValidators,
406
+ typeOperation,
407
+ relationshipValidationType,
408
+ itemIsPartial
409
+ );
410
+ for (const [fieldName, validator] of Object.entries(customValidatorMap)) {
411
+ const field = normalizedFields[fieldName];
412
+ if (!field) {
413
+ continue;
414
+ }
415
+ let error = getNoErrorDescriptor();
416
+ try {
417
+ error = validator(value[fieldName], field);
418
+ } catch (e) {
419
+ error = getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.INVALID_CUSTOM_TYPE);
420
+ }
421
+ if (error.code !== ERROR_MESSAGE_CONSTANTS.NONE) {
422
+ results.valid = false;
423
+ results.errorMap[fieldName] = [
424
+ ...results.errorMap[fieldName] ?? [],
425
+ error
426
+ ];
427
+ if (results.error.code === ERROR_MESSAGE_CONSTANTS.NONE) {
428
+ results.error = error;
429
+ }
430
+ }
431
+ }
432
+ return results;
433
+ };
263
434
  var validateTypeInfoValue = (value, typeInfoFullName, typeInfoMap, strict = false, customValidators, typeOperation, relationshipValidationType, itemIsPartial) => {
264
435
  const typeInfo = typeInfoMap[typeInfoFullName];
265
436
  const results = {
266
437
  typeName: typeInfoFullName,
267
438
  valid: !!typeInfo,
268
- error: !!typeInfo ? "" : ERROR_MESSAGE_CONSTANTS.TYPE_DOES_NOT_EXIST,
439
+ error: !!typeInfo ? getNoErrorDescriptor() : getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.TYPE_DOES_NOT_EXIST),
269
440
  errorMap: {}
270
441
  };
271
442
  if (typeInfo) {
@@ -288,7 +459,7 @@ var validateTypeInfoValue = (value, typeInfoFullName, typeInfoMap, strict = fals
288
459
  const existingError = results.errorMap[oE] ?? [];
289
460
  results.errorMap[oE] = existingError ? [...existingError, ...operationErrorMap[oE]] : operationErrorMap[oE];
290
461
  }
291
- if (!operationValid && operationError) {
462
+ if (!operationValid && operationError.code !== ERROR_MESSAGE_CONSTANTS.NONE) {
292
463
  results.error = operationError;
293
464
  }
294
465
  }
@@ -303,7 +474,9 @@ var validateTypeInfoValue = (value, typeInfoFullName, typeInfoMap, strict = fals
303
474
  }
304
475
  if (!valid) {
305
476
  results.valid = false;
306
- results.error = ERROR_MESSAGE_CONSTANTS.NO_UNION_TYPE_MATCHED;
477
+ results.error = getErrorDescriptor(
478
+ ERROR_MESSAGE_CONSTANTS.NO_UNION_TYPE_MATCHED
479
+ );
307
480
  }
308
481
  } else if (strict) {
309
482
  const knownFields = Object.keys(fields || {});
@@ -311,7 +484,9 @@ var validateTypeInfoValue = (value, typeInfoFullName, typeInfoMap, strict = fals
311
484
  for (const vF of valueFields) {
312
485
  if (!knownFields.includes(vF)) {
313
486
  results.valid = false;
314
- results.errorMap[vF] = [ERROR_MESSAGE_CONSTANTS.INVALID_FIELD];
487
+ results.errorMap[vF] = [
488
+ getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.INVALID_FIELD)
489
+ ];
315
490
  }
316
491
  }
317
492
  }
@@ -336,18 +511,28 @@ var validateTypeInfoValue = (value, typeInfoFullName, typeInfoMap, strict = fals
336
511
  itemIsPartial
337
512
  );
338
513
  results.valid = getValidityValue(results.valid, fieldValid);
339
- results.errorMap[key] = [fieldError];
340
- for (const fE in fieldErrorMap) {
341
- results.errorMap[getPathString([key, fE])] = fieldErrorMap[fE];
514
+ const fieldEntries = [fieldError];
515
+ const arrayItemErrorMap = getArrayItemErrorMap(
516
+ fieldErrorMap[ARRAY_ITEM_ERROR_MAP_KEY]
517
+ );
518
+ if (Object.keys(arrayItemErrorMap).length) {
519
+ fieldEntries.push({ itemErrorMap: arrayItemErrorMap });
520
+ }
521
+ results.errorMap[key] = fieldEntries;
522
+ for (const [fE, entries] of Object.entries(fieldErrorMap)) {
523
+ if (fE === ARRAY_ITEM_ERROR_MAP_KEY) {
524
+ continue;
525
+ }
526
+ results.errorMap[getPathString([key, fE])] = entries;
342
527
  }
343
528
  }
344
529
  }
345
530
  }
346
- if (!results.valid && !results.error) {
347
- results.error = ERROR_MESSAGE_CONSTANTS.INVALID_TYPE;
531
+ if (!results.valid && results.error.code === ERROR_MESSAGE_CONSTANTS.NONE) {
532
+ results.error = getErrorDescriptor(ERROR_MESSAGE_CONSTANTS.INVALID_TYPE);
348
533
  }
349
534
  }
350
535
  return results;
351
536
  };
352
537
 
353
- export { DENIED_TYPE_OPERATIONS, ERROR_MESSAGE_CONSTANTS, INVALID_CUSTOM_TYPE, PRIMITIVE_ERROR_MESSAGE_CONSTANTS, RelationshipValidationType, TYPE_KEYWORD_VALIDATORS, getValidityValue, hasValue, validateArrayOfTypeInfoFieldValues, validateCustomType, validateKeywordType, validateTypeInfoFieldOperationAllowed, validateTypeInfoFieldValue, validateTypeInfoValue, validateTypeOperationAllowed, validateValueMatchesPattern };
538
+ export { DENIED_TYPE_OPERATIONS, ERROR_MESSAGE_CONSTANTS, INVALID_CUSTOM_TYPE, PRIMITIVE_ERROR_MESSAGE_CONSTANTS, RelationshipValidationType, TYPE_KEYWORD_ERROR_MESSAGE_CONSTANTS, TYPE_KEYWORD_VALIDATORS, TypeOperation, getArrayItemErrorMap, getErrorDescriptor, getErrorDescriptors, getNoErrorDescriptor, getValidityValue, hasValue, isArrayErrorDescriptorCollection, validateArrayOfTypeInfoFieldValues, validateCustomType, validateKeywordType, validateTypeInfoDataItem, validateTypeInfoFieldOperationAllowed, validateTypeInfoFieldValue, validateTypeInfoValue, validateTypeOperationAllowed, validateValueMatchesPattern };