@plasius/schema 1.2.6 → 1.2.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/dist/index.cjs CHANGED
@@ -60,6 +60,12 @@ __export(index_exports, {
60
60
  module.exports = __toCommonJS(index_exports);
61
61
 
62
62
  // src/field.builder.ts
63
+ function mergeValidatorResult(previousResult, nextValid) {
64
+ if (previousResult !== true) {
65
+ return previousResult;
66
+ }
67
+ return nextValid;
68
+ }
63
69
  var FieldBuilder = class _FieldBuilder {
64
70
  constructor(type, options = {}) {
65
71
  this.type = type;
@@ -67,6 +73,7 @@ var FieldBuilder = class _FieldBuilder {
67
73
  this.itemType = options.itemType;
68
74
  this.refType = options.refType;
69
75
  }
76
+ type;
70
77
  _type;
71
78
  _storageType;
72
79
  isSystem = false;
@@ -155,19 +162,19 @@ var FieldBuilder = class _FieldBuilder {
155
162
  const prevValidator = this._validator;
156
163
  this._validator = (value) => {
157
164
  const valid = typeof value === "number" && value >= min;
158
- return prevValidator ? prevValidator(value) && valid : valid;
165
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
159
166
  };
160
167
  } else if (this.type === "string") {
161
168
  const prevValidator = this._validator;
162
169
  this._validator = (value) => {
163
170
  const valid = typeof value === "string" && value.length >= min;
164
- return prevValidator ? prevValidator(value) && valid : valid;
171
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
165
172
  };
166
173
  } else if (this.type === "array") {
167
174
  const prevValidator = this._validator;
168
175
  this._validator = (value) => {
169
176
  const valid = Array.isArray(value) && value.length >= min;
170
- return prevValidator ? prevValidator(value) && valid : valid;
177
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
171
178
  };
172
179
  } else {
173
180
  throw new Error(
@@ -181,19 +188,19 @@ var FieldBuilder = class _FieldBuilder {
181
188
  const prevValidator = this._validator;
182
189
  this._validator = (value) => {
183
190
  const valid = typeof value === "number" && value <= max;
184
- return prevValidator ? prevValidator(value) && valid : valid;
191
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
185
192
  };
186
193
  } else if (this.type === "string") {
187
194
  const prevValidator = this._validator;
188
195
  this._validator = (value) => {
189
196
  const valid = typeof value === "string" && value.length <= max;
190
- return prevValidator ? prevValidator(value) && valid : valid;
197
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
191
198
  };
192
199
  } else if (this.type === "array") {
193
200
  const prevValidator = this._validator;
194
201
  this._validator = (value) => {
195
202
  const valid = Array.isArray(value) && value.length <= max;
196
- return prevValidator ? prevValidator(value) && valid : valid;
203
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
197
204
  };
198
205
  } else {
199
206
  throw new Error(
@@ -209,7 +216,7 @@ var FieldBuilder = class _FieldBuilder {
209
216
  const prevValidator = this._validator;
210
217
  this._validator = (value) => {
211
218
  const valid = typeof value === "string" && regex.test(value);
212
- return prevValidator ? prevValidator(value) && valid : valid;
219
+ return prevValidator ? mergeValidatorResult(prevValidator(value), valid) : valid;
213
220
  };
214
221
  return this;
215
222
  }
@@ -1608,6 +1615,38 @@ function getValidator(def) {
1608
1615
  function getShape(def) {
1609
1616
  return def?._shape ?? def?.shape ?? void 0;
1610
1617
  }
1618
+ function normalizeValidationIssue(path, issue, defaultCode) {
1619
+ if (typeof issue === "string") {
1620
+ return {
1621
+ path,
1622
+ code: defaultCode,
1623
+ message: issue
1624
+ };
1625
+ }
1626
+ return {
1627
+ path: issue.path ?? path,
1628
+ code: issue.code || defaultCode,
1629
+ message: issue.message
1630
+ };
1631
+ }
1632
+ function normalizeValidatorIssues(path, result, defaultCode) {
1633
+ if (result === true) {
1634
+ return [];
1635
+ }
1636
+ if (result === false) {
1637
+ return [
1638
+ {
1639
+ path,
1640
+ code: defaultCode,
1641
+ message: `Invalid value for field: ${path}`
1642
+ }
1643
+ ];
1644
+ }
1645
+ if (Array.isArray(result)) {
1646
+ return result.map((issue) => normalizeValidationIssue(path, issue, defaultCode));
1647
+ }
1648
+ return [normalizeValidationIssue(path, result, defaultCode)];
1649
+ }
1611
1650
  function checkMissingRequired(parentKey, key, value, def, errors) {
1612
1651
  if (value === void 0 || value === null) {
1613
1652
  const path = parentKey ? `${parentKey}.${key}` : key;
@@ -1626,13 +1665,16 @@ function checkImmutable(parentKey, key, value, def, existing, errors) {
1626
1665
  }
1627
1666
  return { immutableViolation: false };
1628
1667
  }
1629
- function runCustomValidator(parentKey, key, value, def, errors) {
1668
+ function runCustomValidator(parentKey, key, value, def, errors, issues) {
1630
1669
  const validator = getValidator(def);
1631
1670
  if (validator && value !== void 0 && value !== null) {
1632
- const valid = validator(value);
1633
- if (!valid) {
1634
- const path = parentKey ? `${parentKey}.${key}` : key;
1635
- errors.push(`Invalid value for field: ${path}`);
1671
+ const path = parentKey ? `${parentKey}.${key}` : key;
1672
+ const normalizedIssues = normalizeValidatorIssues(path, validator(value), "invalid_value");
1673
+ if (normalizedIssues.length > 0) {
1674
+ errors.push(...normalizedIssues.map((issue) => issue.message));
1675
+ if (issues) {
1676
+ issues.push(...normalizedIssues);
1677
+ }
1636
1678
  return { invalid: true };
1637
1679
  }
1638
1680
  }
@@ -1672,7 +1714,7 @@ function validateBooleanField(parentKey, key, value, _def, errors) {
1672
1714
  errors.push(`Field ${path} must be boolean`);
1673
1715
  }
1674
1716
  }
1675
- function validateObjectChildren(parentKey, obj, shape, errors, existing, piiEnforcement, logger) {
1717
+ function validateObjectChildren(parentKey, obj, shape, errors, issues, existing, piiEnforcement, logger) {
1676
1718
  for (const [childKey, childDef] of Object.entries(shape)) {
1677
1719
  let childValue = obj[childKey];
1678
1720
  const existingChild = existing && typeof existing === "object" ? existing[childKey] : void 0;
@@ -1713,7 +1755,8 @@ function validateObjectChildren(parentKey, obj, shape, errors, existing, piiEnfo
1713
1755
  childKey,
1714
1756
  childValue,
1715
1757
  childDef,
1716
- errors
1758
+ errors,
1759
+ issues
1717
1760
  );
1718
1761
  if (invalid) continue;
1719
1762
  validateByType(
@@ -1722,13 +1765,14 @@ function validateObjectChildren(parentKey, obj, shape, errors, existing, piiEnfo
1722
1765
  childValue,
1723
1766
  childDef,
1724
1767
  errors,
1768
+ issues,
1725
1769
  existingChild,
1726
1770
  piiEnforcement,
1727
1771
  logger
1728
1772
  );
1729
1773
  }
1730
1774
  }
1731
- function validateObjectField(parentKey, key, value, def, errors, existing, piiEnforcement, logger) {
1775
+ function validateObjectField(parentKey, key, value, def, errors, issues, existing, piiEnforcement, logger) {
1732
1776
  const path = parentKey ? `${parentKey}.${key}` : key;
1733
1777
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
1734
1778
  errors.push(`Field ${path} must be object`);
@@ -1736,7 +1780,7 @@ function validateObjectField(parentKey, key, value, def, errors, existing, piiEn
1736
1780
  }
1737
1781
  const objShape = getShape(def);
1738
1782
  if (objShape)
1739
- validateObjectChildren(path, value, objShape, errors, existing, piiEnforcement, logger);
1783
+ validateObjectChildren(path, value, objShape, errors, issues, existing, piiEnforcement, logger);
1740
1784
  }
1741
1785
  function validateArrayOfStrings(parentKey, key, arr, itemDef, errors) {
1742
1786
  const path = parentKey ? `${parentKey}.${key}` : key;
@@ -1795,7 +1839,7 @@ function validateArrayOfBooleans(parentKey, key, arr, _itemDef, errors) {
1795
1839
  });
1796
1840
  }
1797
1841
  }
1798
- function validateArrayOfObjects(parentKey, key, arr, itemDef, errors, existing, piiEnforcement, logger) {
1842
+ function validateArrayOfObjects(parentKey, key, arr, itemDef, errors, issues, existing, piiEnforcement, logger) {
1799
1843
  const path = parentKey ? `${parentKey}.${key}` : key;
1800
1844
  if (!Array.isArray(arr) || !arr.every((v) => typeof v === "object" && v !== null && !Array.isArray(v))) {
1801
1845
  errors.push(`Field ${path} must be object[]`);
@@ -1849,7 +1893,8 @@ function validateArrayOfObjects(parentKey, key, arr, itemDef, errors, existing,
1849
1893
  childKey,
1850
1894
  childValue,
1851
1895
  childDef,
1852
- errors
1896
+ errors,
1897
+ issues
1853
1898
  );
1854
1899
  if (invalid) continue;
1855
1900
  validateByType(
@@ -1858,6 +1903,7 @@ function validateArrayOfObjects(parentKey, key, arr, itemDef, errors, existing,
1858
1903
  childValue,
1859
1904
  childDef,
1860
1905
  errors,
1906
+ issues,
1861
1907
  existingChild,
1862
1908
  piiEnforcement,
1863
1909
  logger
@@ -1865,7 +1911,7 @@ function validateArrayOfObjects(parentKey, key, arr, itemDef, errors, existing,
1865
1911
  }
1866
1912
  });
1867
1913
  }
1868
- function validateArrayField(parentKey, key, value, def, errors, existing, piiEnforcement, logger) {
1914
+ function validateArrayField(parentKey, key, value, def, errors, issues, existing, piiEnforcement, logger) {
1869
1915
  const path = parentKey ? `${parentKey}.${key}` : key;
1870
1916
  if (!Array.isArray(value)) {
1871
1917
  errors.push(`Field ${key} must be an array`);
@@ -1885,6 +1931,7 @@ function validateArrayField(parentKey, key, value, def, errors, existing, piiEnf
1885
1931
  value,
1886
1932
  def.itemType,
1887
1933
  errors,
1934
+ issues,
1888
1935
  existing,
1889
1936
  piiEnforcement,
1890
1937
  logger
@@ -1941,9 +1988,14 @@ function validateArrayField(parentKey, key, value, def, errors, existing, piiEnf
1941
1988
  if (shortCircuit) continue;
1942
1989
  const childValidator = getValidator(childDef);
1943
1990
  if (childValidator && childValue !== void 0 && childValue !== null) {
1944
- const valid = childValidator(childValue);
1945
- if (!valid) {
1946
- errors.push(`Invalid value for field: ${childPath}`);
1991
+ const normalizedIssues = normalizeValidatorIssues(
1992
+ childPath,
1993
+ childValidator(childValue),
1994
+ "invalid_value"
1995
+ );
1996
+ if (normalizedIssues.length > 0) {
1997
+ errors.push(...normalizedIssues.map((issue) => issue.message));
1998
+ issues.push(...normalizedIssues);
1947
1999
  continue;
1948
2000
  }
1949
2001
  }
@@ -1953,6 +2005,7 @@ function validateArrayField(parentKey, key, value, def, errors, existing, piiEnf
1953
2005
  childValue,
1954
2006
  childDef,
1955
2007
  errors,
2008
+ issues,
1956
2009
  existingChild,
1957
2010
  piiEnforcement,
1958
2011
  logger
@@ -1978,7 +2031,7 @@ function validateRefField(parentKey, key, value, def, errors, _existing, _piiEnf
1978
2031
  );
1979
2032
  }
1980
2033
  }
1981
- function validateByType(parentKey, key, value, def, errors, existing, piiEnforcement, logger) {
2034
+ function validateByType(parentKey, key, value, def, errors, issues, existing, piiEnforcement, logger) {
1982
2035
  const path = parentKey ? `${parentKey}.${key}` : key;
1983
2036
  switch (def.type) {
1984
2037
  case "string":
@@ -1994,6 +2047,7 @@ function validateByType(parentKey, key, value, def, errors, existing, piiEnforce
1994
2047
  value,
1995
2048
  def,
1996
2049
  errors,
2050
+ issues,
1997
2051
  existing,
1998
2052
  piiEnforcement,
1999
2053
  logger
@@ -2005,6 +2059,7 @@ function validateByType(parentKey, key, value, def, errors, existing, piiEnforce
2005
2059
  value,
2006
2060
  def,
2007
2061
  errors,
2062
+ issues,
2008
2063
  existing,
2009
2064
  piiEnforcement,
2010
2065
  logger
@@ -2040,6 +2095,7 @@ function createSchema(_shape, entityType, options = {
2040
2095
  // 🔗 Validate input against the schema
2041
2096
  validate(input, existing) {
2042
2097
  const errors = [];
2098
+ const issues = [];
2043
2099
  const result = {};
2044
2100
  const piiMode = options.piiEnforcement ?? "none";
2045
2101
  if (typeof input !== "object" || input === null) {
@@ -2103,16 +2159,19 @@ function createSchema(_shape, entityType, options = {
2103
2159
  if (shortCircuit) continue;
2104
2160
  const validateField = (val) => {
2105
2161
  const localErrors = [];
2162
+ const localIssues = [];
2106
2163
  const { invalid } = runCustomValidator(
2107
2164
  "",
2108
2165
  key,
2109
2166
  val,
2110
2167
  def,
2111
- localErrors
2168
+ localErrors,
2169
+ localIssues
2112
2170
  );
2113
2171
  if (!invalid) {
2114
- validateByType("", key, val, def, localErrors, existingField, piiMode, console);
2172
+ validateByType("", key, val, def, localErrors, localIssues, existingField, piiMode, console);
2115
2173
  }
2174
+ issues.push(...localIssues);
2116
2175
  return localErrors;
2117
2176
  };
2118
2177
  let fieldValue = value;
@@ -2153,7 +2212,8 @@ function createSchema(_shape, entityType, options = {
2153
2212
  return {
2154
2213
  valid: errors.length === 0,
2155
2214
  value: result,
2156
- errors
2215
+ errors,
2216
+ issues
2157
2217
  };
2158
2218
  },
2159
2219
  // specific validator for a schema to allow conditional validation