@plasius/schema 1.2.6 → 1.2.7

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