reliant-type 1.0.0

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 (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1305 -0
  3. package/dist/cjs/constants/SECURITY_CONSTANTS.js +49 -0
  4. package/dist/cjs/constants/SECURITY_CONSTANTS.js.map +1 -0
  5. package/dist/cjs/constants/VALIDATION_CONSTANTS.js +103 -0
  6. package/dist/cjs/constants/VALIDATION_CONSTANTS.js.map +1 -0
  7. package/dist/cjs/core/schema/extensions/SmartInference.js +200 -0
  8. package/dist/cjs/core/schema/extensions/SmartInference.js.map +1 -0
  9. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/Docs.js +100 -0
  10. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/Docs.js.map +1 -0
  11. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js +192 -0
  12. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js.map +1 -0
  13. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js +174 -0
  14. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js.map +1 -0
  15. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js +54 -0
  16. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js.map +1 -0
  17. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js +50 -0
  18. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js.map +1 -0
  19. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/index.js +15 -0
  20. package/dist/cjs/core/schema/extensions/components/AutoDocumentation/index.js.map +1 -0
  21. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js +70 -0
  22. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js.map +1 -0
  23. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js +40 -0
  24. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js.map +1 -0
  25. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js +19 -0
  26. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js.map +1 -0
  27. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js +20 -0
  28. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js.map +1 -0
  29. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js +49 -0
  30. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js.map +1 -0
  31. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/index.js +98 -0
  32. package/dist/cjs/core/schema/extensions/components/ConditionalValidation/index.js.map +1 -0
  33. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/FormValidator.js +85 -0
  34. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/FormValidator.js.map +1 -0
  35. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/LiveValidator.js +133 -0
  36. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/LiveValidator.js.map +1 -0
  37. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/StreamValidator.js +351 -0
  38. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/StreamValidator.js.map +1 -0
  39. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/index.js +109 -0
  40. package/dist/cjs/core/schema/extensions/components/RealtimeValidation/index.js.map +1 -0
  41. package/dist/cjs/core/schema/extensions/index.js +61 -0
  42. package/dist/cjs/core/schema/extensions/index.js.map +1 -0
  43. package/dist/cjs/core/schema/extensions/mods/index.js +51 -0
  44. package/dist/cjs/core/schema/extensions/mods/index.js.map +1 -0
  45. package/dist/cjs/core/schema/extensions/mods/openapi-converter.js +227 -0
  46. package/dist/cjs/core/schema/extensions/mods/openapi-converter.js.map +1 -0
  47. package/dist/cjs/core/schema/extensions/mods/typescript-generator.js +287 -0
  48. package/dist/cjs/core/schema/extensions/mods/typescript-generator.js.map +1 -0
  49. package/dist/cjs/core/schema/extensions/mods/validation-engine.js +224 -0
  50. package/dist/cjs/core/schema/extensions/mods/validation-engine.js.map +1 -0
  51. package/dist/cjs/core/schema/mode/interfaces/Interface.js +277 -0
  52. package/dist/cjs/core/schema/mode/interfaces/Interface.js.map +1 -0
  53. package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js +1431 -0
  54. package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -0
  55. package/dist/cjs/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js +520 -0
  56. package/dist/cjs/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js.map +1 -0
  57. package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js +624 -0
  58. package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js.map +1 -0
  59. package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js +811 -0
  60. package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js.map +1 -0
  61. package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js +599 -0
  62. package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js.map +1 -0
  63. package/dist/cjs/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js +89 -0
  64. package/dist/cjs/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js.map +1 -0
  65. package/dist/cjs/core/schema/mode/interfaces/errors/ErrorHandler.js +356 -0
  66. package/dist/cjs/core/schema/mode/interfaces/errors/ErrorHandler.js.map +1 -0
  67. package/dist/cjs/core/schema/mode/interfaces/errors/types/errors.type.js +80 -0
  68. package/dist/cjs/core/schema/mode/interfaces/errors/types/errors.type.js.map +1 -0
  69. package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +778 -0
  70. package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -0
  71. package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +523 -0
  72. package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -0
  73. package/dist/cjs/core/schema/mode/interfaces/typescript/ConditionalTypes.js +681 -0
  74. package/dist/cjs/core/schema/mode/interfaces/typescript/ConditionalTypes.js.map +1 -0
  75. package/dist/cjs/core/schema/mode/interfaces/typescript/IDESupport.js +430 -0
  76. package/dist/cjs/core/schema/mode/interfaces/typescript/IDESupport.js.map +1 -0
  77. package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js +225 -0
  78. package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -0
  79. package/dist/cjs/core/schema/mode/interfaces/typescript/index.js +44 -0
  80. package/dist/cjs/core/schema/mode/interfaces/typescript/index.js.map +1 -0
  81. package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js +1134 -0
  82. package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -0
  83. package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js +256 -0
  84. package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -0
  85. package/dist/cjs/core/schema/mode/interfaces/validators/TypeValidators.js +429 -0
  86. package/dist/cjs/core/schema/mode/interfaces/validators/TypeValidators.js.map +1 -0
  87. package/dist/cjs/core/schema/mode/interfaces/validators/UnionCache.js +404 -0
  88. package/dist/cjs/core/schema/mode/interfaces/validators/UnionCache.js.map +1 -0
  89. package/dist/cjs/core/schema/mode/interfaces/validators/ValidationHelpers.js +851 -0
  90. package/dist/cjs/core/schema/mode/interfaces/validators/ValidationHelpers.js.map +1 -0
  91. package/dist/cjs/core/schema/mode/interfaces/validators/mods/passValidator.js +262 -0
  92. package/dist/cjs/core/schema/mode/interfaces/validators/mods/passValidator.js.map +1 -0
  93. package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js +887 -0
  94. package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -0
  95. package/dist/cjs/core/schema/mode/interfaces/validators/mods/urlValidation.js +191 -0
  96. package/dist/cjs/core/schema/mode/interfaces/validators/mods/urlValidation.js.map +1 -0
  97. package/dist/cjs/core/schema/optimization/ObjectValidationCache.js +462 -0
  98. package/dist/cjs/core/schema/optimization/ObjectValidationCache.js.map +1 -0
  99. package/dist/cjs/core/schema/optimization/PerformanceMonitor.js +773 -0
  100. package/dist/cjs/core/schema/optimization/PerformanceMonitor.js.map +1 -0
  101. package/dist/cjs/core/schema/optimization/SchemaCompiler.js +600 -0
  102. package/dist/cjs/core/schema/optimization/SchemaCompiler.js.map +1 -0
  103. package/dist/cjs/core/types/ValidatorTypes.js +70 -0
  104. package/dist/cjs/core/types/ValidatorTypes.js.map +1 -0
  105. package/dist/cjs/core/types/parser.type.js +12 -0
  106. package/dist/cjs/core/types/parser.type.js.map +1 -0
  107. package/dist/cjs/core/utils/Make.js +61 -0
  108. package/dist/cjs/core/utils/Make.js.map +1 -0
  109. package/dist/cjs/core/utils/Mod.js +1033 -0
  110. package/dist/cjs/core/utils/Mod.js.map +1 -0
  111. package/dist/cjs/core/utils/UrlArgs.js +102 -0
  112. package/dist/cjs/core/utils/UrlArgs.js.map +1 -0
  113. package/dist/cjs/core/utils/arrayToEnum.js +18 -0
  114. package/dist/cjs/core/utils/arrayToEnum.js.map +1 -0
  115. package/dist/cjs/core/utils/createUrlArgsEnumFArray.js +13 -0
  116. package/dist/cjs/core/utils/createUrlArgsEnumFArray.js.map +1 -0
  117. package/dist/cjs/core/utils/securityHelpers.js +215 -0
  118. package/dist/cjs/core/utils/securityHelpers.js.map +1 -0
  119. package/dist/cjs/core/utils/securityValidatorHelpers.js +65 -0
  120. package/dist/cjs/core/utils/securityValidatorHelpers.js.map +1 -0
  121. package/dist/cjs/index.js +31 -0
  122. package/dist/cjs/index.js.map +1 -0
  123. package/dist/cjs/package.json +3 -0
  124. package/dist/esm/constants/SECURITY_CONSTANTS.js +47 -0
  125. package/dist/esm/constants/SECURITY_CONSTANTS.js.map +1 -0
  126. package/dist/esm/constants/VALIDATION_CONSTANTS.js +98 -0
  127. package/dist/esm/constants/VALIDATION_CONSTANTS.js.map +1 -0
  128. package/dist/esm/core/schema/extensions/SmartInference.js +197 -0
  129. package/dist/esm/core/schema/extensions/SmartInference.js.map +1 -0
  130. package/dist/esm/core/schema/extensions/components/AutoDocumentation/Docs.js +98 -0
  131. package/dist/esm/core/schema/extensions/components/AutoDocumentation/Docs.js.map +1 -0
  132. package/dist/esm/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js +190 -0
  133. package/dist/esm/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js.map +1 -0
  134. package/dist/esm/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js +172 -0
  135. package/dist/esm/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js.map +1 -0
  136. package/dist/esm/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js +52 -0
  137. package/dist/esm/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js.map +1 -0
  138. package/dist/esm/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js +48 -0
  139. package/dist/esm/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js.map +1 -0
  140. package/dist/esm/core/schema/extensions/components/AutoDocumentation/index.js +12 -0
  141. package/dist/esm/core/schema/extensions/components/AutoDocumentation/index.js.map +1 -0
  142. package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js +68 -0
  143. package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js.map +1 -0
  144. package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js +38 -0
  145. package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js.map +1 -0
  146. package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js +17 -0
  147. package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js.map +1 -0
  148. package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js +18 -0
  149. package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js.map +1 -0
  150. package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js +45 -0
  151. package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js.map +1 -0
  152. package/dist/esm/core/schema/extensions/components/ConditionalValidation/index.js +92 -0
  153. package/dist/esm/core/schema/extensions/components/ConditionalValidation/index.js.map +1 -0
  154. package/dist/esm/core/schema/extensions/components/RealtimeValidation/FormValidator.js +83 -0
  155. package/dist/esm/core/schema/extensions/components/RealtimeValidation/FormValidator.js.map +1 -0
  156. package/dist/esm/core/schema/extensions/components/RealtimeValidation/LiveValidator.js +131 -0
  157. package/dist/esm/core/schema/extensions/components/RealtimeValidation/LiveValidator.js.map +1 -0
  158. package/dist/esm/core/schema/extensions/components/RealtimeValidation/StreamValidator.js +349 -0
  159. package/dist/esm/core/schema/extensions/components/RealtimeValidation/StreamValidator.js.map +1 -0
  160. package/dist/esm/core/schema/extensions/components/RealtimeValidation/index.js +103 -0
  161. package/dist/esm/core/schema/extensions/components/RealtimeValidation/index.js.map +1 -0
  162. package/dist/esm/core/schema/extensions/index.js +53 -0
  163. package/dist/esm/core/schema/extensions/index.js.map +1 -0
  164. package/dist/esm/core/schema/extensions/mods/index.js +47 -0
  165. package/dist/esm/core/schema/extensions/mods/index.js.map +1 -0
  166. package/dist/esm/core/schema/extensions/mods/openapi-converter.js +225 -0
  167. package/dist/esm/core/schema/extensions/mods/openapi-converter.js.map +1 -0
  168. package/dist/esm/core/schema/extensions/mods/typescript-generator.js +284 -0
  169. package/dist/esm/core/schema/extensions/mods/typescript-generator.js.map +1 -0
  170. package/dist/esm/core/schema/extensions/mods/validation-engine.js +222 -0
  171. package/dist/esm/core/schema/extensions/mods/validation-engine.js.map +1 -0
  172. package/dist/esm/core/schema/mode/interfaces/Interface.js +269 -0
  173. package/dist/esm/core/schema/mode/interfaces/Interface.js.map +1 -0
  174. package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js +1429 -0
  175. package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -0
  176. package/dist/esm/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js +518 -0
  177. package/dist/esm/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js.map +1 -0
  178. package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js +620 -0
  179. package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js.map +1 -0
  180. package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js +809 -0
  181. package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js.map +1 -0
  182. package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js +597 -0
  183. package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js.map +1 -0
  184. package/dist/esm/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js +89 -0
  185. package/dist/esm/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js.map +1 -0
  186. package/dist/esm/core/schema/mode/interfaces/errors/ErrorHandler.js +354 -0
  187. package/dist/esm/core/schema/mode/interfaces/errors/ErrorHandler.js.map +1 -0
  188. package/dist/esm/core/schema/mode/interfaces/errors/types/errors.type.js +80 -0
  189. package/dist/esm/core/schema/mode/interfaces/errors/types/errors.type.js.map +1 -0
  190. package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +776 -0
  191. package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -0
  192. package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +521 -0
  193. package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -0
  194. package/dist/esm/core/schema/mode/interfaces/typescript/ConditionalTypes.js +681 -0
  195. package/dist/esm/core/schema/mode/interfaces/typescript/ConditionalTypes.js.map +1 -0
  196. package/dist/esm/core/schema/mode/interfaces/typescript/IDESupport.js +428 -0
  197. package/dist/esm/core/schema/mode/interfaces/typescript/IDESupport.js.map +1 -0
  198. package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js +223 -0
  199. package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -0
  200. package/dist/esm/core/schema/mode/interfaces/typescript/index.js +35 -0
  201. package/dist/esm/core/schema/mode/interfaces/typescript/index.js.map +1 -0
  202. package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js +1132 -0
  203. package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -0
  204. package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js +254 -0
  205. package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -0
  206. package/dist/esm/core/schema/mode/interfaces/validators/TypeValidators.js +427 -0
  207. package/dist/esm/core/schema/mode/interfaces/validators/TypeValidators.js.map +1 -0
  208. package/dist/esm/core/schema/mode/interfaces/validators/UnionCache.js +400 -0
  209. package/dist/esm/core/schema/mode/interfaces/validators/UnionCache.js.map +1 -0
  210. package/dist/esm/core/schema/mode/interfaces/validators/ValidationHelpers.js +849 -0
  211. package/dist/esm/core/schema/mode/interfaces/validators/ValidationHelpers.js.map +1 -0
  212. package/dist/esm/core/schema/mode/interfaces/validators/mods/passValidator.js +260 -0
  213. package/dist/esm/core/schema/mode/interfaces/validators/mods/passValidator.js.map +1 -0
  214. package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js +881 -0
  215. package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -0
  216. package/dist/esm/core/schema/mode/interfaces/validators/mods/urlValidation.js +189 -0
  217. package/dist/esm/core/schema/mode/interfaces/validators/mods/urlValidation.js.map +1 -0
  218. package/dist/esm/core/schema/optimization/ObjectValidationCache.js +460 -0
  219. package/dist/esm/core/schema/optimization/ObjectValidationCache.js.map +1 -0
  220. package/dist/esm/core/schema/optimization/PerformanceMonitor.js +771 -0
  221. package/dist/esm/core/schema/optimization/PerformanceMonitor.js.map +1 -0
  222. package/dist/esm/core/schema/optimization/SchemaCompiler.js +598 -0
  223. package/dist/esm/core/schema/optimization/SchemaCompiler.js.map +1 -0
  224. package/dist/esm/core/types/ValidatorTypes.js +65 -0
  225. package/dist/esm/core/types/ValidatorTypes.js.map +1 -0
  226. package/dist/esm/core/types/parser.type.js +12 -0
  227. package/dist/esm/core/types/parser.type.js.map +1 -0
  228. package/dist/esm/core/utils/Make.js +59 -0
  229. package/dist/esm/core/utils/Make.js.map +1 -0
  230. package/dist/esm/core/utils/Mod.js +1031 -0
  231. package/dist/esm/core/utils/Mod.js.map +1 -0
  232. package/dist/esm/core/utils/UrlArgs.js +98 -0
  233. package/dist/esm/core/utils/UrlArgs.js.map +1 -0
  234. package/dist/esm/core/utils/arrayToEnum.js +16 -0
  235. package/dist/esm/core/utils/arrayToEnum.js.map +1 -0
  236. package/dist/esm/core/utils/createUrlArgsEnumFArray.js +11 -0
  237. package/dist/esm/core/utils/createUrlArgsEnumFArray.js.map +1 -0
  238. package/dist/esm/core/utils/securityHelpers.js +207 -0
  239. package/dist/esm/core/utils/securityHelpers.js.map +1 -0
  240. package/dist/esm/core/utils/securityValidatorHelpers.js +62 -0
  241. package/dist/esm/core/utils/securityValidatorHelpers.js.map +1 -0
  242. package/dist/esm/index.js +12 -0
  243. package/dist/esm/index.js.map +1 -0
  244. package/dist/esm/package.json +3 -0
  245. package/dist/schema.d.ts +2595 -0
  246. package/docs/ALL_TYPES.md +120 -0
  247. package/docs/API-STABILITY.md +336 -0
  248. package/docs/CONDITIONAL-VALIDATION.md +637 -0
  249. package/docs/EXAMPLES.md +876 -0
  250. package/docs/FIELD-TYPES.md +829 -0
  251. package/docs/GETTING-STARTED.md +394 -0
  252. package/docs/LIVE-UTILITY.md +1137 -0
  253. package/docs/QUICK-REFERENCE.md +346 -0
  254. package/docs/README.md +205 -0
  255. package/docs/VSCODE-EXTENSION.md +458 -0
  256. package/package.json +219 -0
  257. package/src/bench/BENCHMARK-RESULTS.md +211 -0
  258. package/src/bench/benchmark-results.json +148 -0
  259. package/src/bench/performance-comparison.ts +218 -0
  260. package/src/bench/precompilation-benchmark.ts +218 -0
  261. package/src/constants/SECURITY_CONSTANTS.ts +44 -0
  262. package/src/constants/VALIDATION_CONSTANTS.ts +176 -0
  263. package/src/core/README.md +395 -0
  264. package/src/core/compiler/SchemaTransformer.ts +279 -0
  265. package/src/core/compiler/TypeAnalyzer.ts +378 -0
  266. package/src/core/compiler/TypeScriptCompilerIntegration.ts +220 -0
  267. package/src/core/compiler/TypeToSchemaConverter.ts +288 -0
  268. package/src/core/index.ts +70 -0
  269. package/src/core/schema/extensions/AutoDocumentation.ts +572 -0
  270. package/src/core/schema/extensions/ConditionalValidation.ts +330 -0
  271. package/src/core/schema/extensions/README.md +171 -0
  272. package/src/core/schema/extensions/RealtimeValidation.ts +656 -0
  273. package/src/core/schema/extensions/SmartInference.ts +224 -0
  274. package/src/core/schema/extensions/components/AutoDocumentation/Docs.ts +98 -0
  275. package/src/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.ts +201 -0
  276. package/src/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.ts +176 -0
  277. package/src/core/schema/extensions/components/AutoDocumentation/OpenAPIGenerator.ts +175 -0
  278. package/src/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.ts +49 -0
  279. package/src/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.ts +54 -0
  280. package/src/core/schema/extensions/components/AutoDocumentation/index.ts +17 -0
  281. package/src/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.ts +101 -0
  282. package/src/core/schema/extensions/components/ConditionalValidation/ConditionalElse.ts +65 -0
  283. package/src/core/schema/extensions/components/ConditionalValidation/ConditionalThen.ts +33 -0
  284. package/src/core/schema/extensions/components/ConditionalValidation/Extend.ts +75 -0
  285. package/src/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.ts +16 -0
  286. package/src/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.ts +50 -0
  287. package/src/core/schema/extensions/components/ConditionalValidation/index.ts +104 -0
  288. package/src/core/schema/extensions/components/RealtimeValidation/FormValidator.ts +88 -0
  289. package/src/core/schema/extensions/components/RealtimeValidation/LiveValidator.ts +171 -0
  290. package/src/core/schema/extensions/components/RealtimeValidation/StreamValidator.ts +397 -0
  291. package/src/core/schema/extensions/components/RealtimeValidation/index.ts +114 -0
  292. package/src/core/schema/extensions/index.ts +76 -0
  293. package/src/core/schema/extensions/mods/index.ts +131 -0
  294. package/src/core/schema/extensions/mods/openapi-converter.ts +338 -0
  295. package/src/core/schema/extensions/mods/typescript-generator.ts +379 -0
  296. package/src/core/schema/extensions/mods/validation-engine.ts +295 -0
  297. package/src/core/schema/mode/interfaces/Interface.ts +364 -0
  298. package/src/core/schema/mode/interfaces/InterfaceSchema.ts +1838 -0
  299. package/src/core/schema/mode/interfaces/README.md +278 -0
  300. package/src/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.ts +657 -0
  301. package/src/core/schema/mode/interfaces/conditional/parser/ConditionalAST.ts +826 -0
  302. package/src/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.ts +992 -0
  303. package/src/core/schema/mode/interfaces/conditional/parser/ConditionalParser.ts +803 -0
  304. package/src/core/schema/mode/interfaces/conditional/parser/readme.md +406 -0
  305. package/src/core/schema/mode/interfaces/conditional/types/ConditionalTypes.ts +273 -0
  306. package/src/core/schema/mode/interfaces/errors/ErrorHandler.ts +624 -0
  307. package/src/core/schema/mode/interfaces/errors/types/errors.type.ts +102 -0
  308. package/src/core/schema/mode/interfaces/precompilation/FieldPrecompilers.ts +962 -0
  309. package/src/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.ts +667 -0
  310. package/src/core/schema/mode/interfaces/typescript/ConditionalTypes.ts +1534 -0
  311. package/src/core/schema/mode/interfaces/typescript/IDESupport.ts +534 -0
  312. package/src/core/schema/mode/interfaces/typescript/TypeInference.ts +737 -0
  313. package/src/core/schema/mode/interfaces/typescript/index.ts +92 -0
  314. package/src/core/schema/mode/interfaces/validators/ConstraintParser.ts +1438 -0
  315. package/src/core/schema/mode/interfaces/validators/EnhancedErrorReporting.ts +227 -0
  316. package/src/core/schema/mode/interfaces/validators/TypeGuards.ts +288 -0
  317. package/src/core/schema/mode/interfaces/validators/TypeValidators.ts +660 -0
  318. package/src/core/schema/mode/interfaces/validators/UnionCache.ts +508 -0
  319. package/src/core/schema/mode/interfaces/validators/ValidationHelpers.ts +1257 -0
  320. package/src/core/schema/mode/interfaces/validators/index.ts +21 -0
  321. package/src/core/schema/mode/interfaces/validators/mods/passValidator.ts +424 -0
  322. package/src/core/schema/mode/interfaces/validators/mods/securityValidator.ts +1634 -0
  323. package/src/core/schema/mode/interfaces/validators/mods/urlValidation.ts +333 -0
  324. package/src/core/schema/optimization/ObjectValidationCache.ts +560 -0
  325. package/src/core/schema/optimization/PerformanceInitializer.ts +188 -0
  326. package/src/core/schema/optimization/PerformanceMonitor.ts +898 -0
  327. package/src/core/schema/optimization/SchemaCompiler.ts +730 -0
  328. package/src/core/testing/TestDataGenerator.ts +590 -0
  329. package/src/core/types/SchemaValidator.type.ts +210 -0
  330. package/src/core/types/ValidatorTypes.ts +93 -0
  331. package/src/core/types/extension.type.ts +109 -0
  332. package/src/core/types/objValidationCache.ts +17 -0
  333. package/src/core/types/parser.type.ts +15 -0
  334. package/src/core/types/perfoMonitor.ts +37 -0
  335. package/src/core/types/scompiler.ts +22 -0
  336. package/src/core/types/securityValidator.type.ts +10 -0
  337. package/src/core/types/types.ts +154 -0
  338. package/src/core/utils/Make.ts +97 -0
  339. package/src/core/utils/Mod.ts +1168 -0
  340. package/src/core/utils/UrlArgs.ts +124 -0
  341. package/src/core/utils/arrayToEnum.ts +89 -0
  342. package/src/core/utils/createUrlArgsEnumFArray.ts +11 -0
  343. package/src/core/utils/securityHelpers.ts +341 -0
  344. package/src/core/utils/securityValidatorHelpers.ts +76 -0
  345. package/src/index.ts +124 -0
@@ -0,0 +1,1838 @@
1
+ /**
2
+ * TypeScript Interface-like Schema Definition System
3
+ *
4
+ * Allows defining schemas using TypeScript-like syntax with string literals
5
+ * that feel natural and are much easier to read and write.
6
+ */
7
+
8
+ import {
9
+ SchemaInterface,
10
+ SchemaFieldType,
11
+ SchemaOptions,
12
+ type CompiledField,
13
+ type AllowUnknownSchema,
14
+ } from "../../../types/SchemaValidator.type";
15
+ import { SchemaValidationResult, ValidationError } from "../../../types/types";
16
+
17
+ import { ConstraintParser, TypeGuards, ValidationHelpers } from "./validators";
18
+ import { ErrorHandler } from "./errors/ErrorHandler";
19
+
20
+ // Import our conditional validation system
21
+ import { ConditionalParser } from "./conditional/parser/ConditionalParser";
22
+ import { ConditionalEvaluator } from "./conditional/evaluator/ConditionalEvaluator";
23
+
24
+ import { ConditionalNode } from "./conditional/types/ConditionalTypes";
25
+
26
+ // Import performance optimization system
27
+ import { SchemaCompiler } from "../../optimization/SchemaCompiler";
28
+ import { ObjectValidationCache } from "../../optimization/ObjectValidationCache";
29
+ import { PerformanceMonitor } from "../../optimization/PerformanceMonitor";
30
+
31
+ // Import precompilation system
32
+ import {
33
+ SchemaPrecompiler,
34
+ PrecompiledValidator,
35
+ OptimizationLevel,
36
+ } from "./precompilation/SchemaPrecompiler";
37
+ import { MAX_OBJECT_DEPTH } from "../../../../constants/VALIDATION_CONSTANTS";
38
+ import { SchemaValidationError } from "./Interface";
39
+ import { ErrorCode } from "./errors/types/errors.type";
40
+
41
+ /**
42
+ * Interface Schema class for TypeScript-like schema definitions
43
+ */
44
+
45
+ export class InterfaceSchema<T = any> {
46
+ private compiledFields: CompiledField[] = [];
47
+ private schemaKeys: string[] = [];
48
+ private ConditionalParser: ConditionalParser;
49
+ private compiledValidator?: any;
50
+ private schemaComplexity: number = 0;
51
+ private isOptimized: boolean = false;
52
+
53
+ // ULTRA-OPTIMIZED: Precompiled validator for maximum performance
54
+ private precompiledValidator?: PrecompiledValidator;
55
+ private optimizationLevel: OptimizationLevel = OptimizationLevel.NONE;
56
+
57
+ constructor(
58
+ private definition: SchemaInterface,
59
+ private options: SchemaOptions = {}
60
+ ) {
61
+ // Initialize conditional parser
62
+ this.ConditionalParser = new ConditionalParser({
63
+ allowNestedConditionals: true,
64
+ maxNestingDepth: MAX_OBJECT_DEPTH,
65
+ strictMode: false,
66
+ enableDebug: false,
67
+ });
68
+
69
+ // ULTRA-OPTIMIZED: Pre-compile schema with advanced optimization
70
+ this.precompileSchema();
71
+
72
+ // Apply performance optimizations (skip if requested to prevent circular dependency)
73
+ if (!this.options.skipOptimization) {
74
+ this.applyOptimizations();
75
+
76
+ // Create precompiled validator for maximum speed
77
+ this.createPrecompiledValidator();
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Check if a field type uses conditional syntax using secure regex pattern
83
+ */
84
+ private isConditionalSyntax(fieldType: string): boolean {
85
+ // Secure regex pattern to match: when <condition> *? <thenValue> [: <elseValue>]
86
+ const conditionalPattern = /^\s*when\s+.+?\s*\*\?\s*.+/;
87
+ return conditionalPattern.test(fieldType);
88
+ }
89
+
90
+ /**
91
+ * Apply performance optimizations based on schema characteristics
92
+ */
93
+ private applyOptimizations(): void {
94
+ // Calculate schema complexity
95
+ this.schemaComplexity = this.calculateComplexity();
96
+
97
+ // Check if schema has conditional fields
98
+ const hasConditionalFields = this.compiledFields.some(
99
+ (field) => field.isConditional
100
+ );
101
+
102
+ // Check nesting depth to avoid optimization bugs with deep nested objects
103
+ const maxNestingDepth = this.calculateMaxNestingDepth();
104
+
105
+ // debugging optimization decisions:
106
+ //// console.log(`[DEBUG] Schema optimization analysis:
107
+ // - Complexity: ${this.schemaComplexity}
108
+ // - Has conditionals: ${hasConditionalFields}
109
+ // - Max nesting depth: ${maxNestingDepth}
110
+ // - Will use advanced optimization: ${this.schemaComplexity > 15 && !hasConditionalFields && maxNestingDepth <= 3}
111
+ // - Will use caching: ${this.schemaComplexity > 5 && !hasConditionalFields && maxNestingDepth <= 3}`);
112
+
113
+ // Apply optimizations based on complexity, but avoid advanced optimizations for conditional fields or deep nesting
114
+ if (
115
+ this.schemaComplexity > 15 &&
116
+ !hasConditionalFields &&
117
+ maxNestingDepth <= 3
118
+ ) {
119
+ // High complexity, no conditionals, shallow nesting - use advanced optimizations
120
+ this.compiledValidator = SchemaCompiler.compileSchema(
121
+ this.definition,
122
+ this.options
123
+ );
124
+ this.isOptimized = true;
125
+ } else if (
126
+ this.schemaComplexity > 5 &&
127
+ !hasConditionalFields &&
128
+ maxNestingDepth <= 3
129
+ ) {
130
+ // Medium complexity, no conditionals, shallow nesting - use caching
131
+ this.isOptimized = true;
132
+ }
133
+ // Note: Conditional fields or deep nesting use the standard validation path for reliability
134
+
135
+ // Start performance monitoring if enabled
136
+ if (this.options.enablePerformanceMonitoring) {
137
+ PerformanceMonitor.startMonitoring();
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Create precompiled validator for maximum speed
143
+ * SAFETY: Now includes recursion protection and cycle detection
144
+ */
145
+ private createPrecompiledValidator(): void {
146
+ // Only create precompiled validator for non-conditional schemas and non-loose mode
147
+ const hasConditionalFields = this.compiledFields.some(
148
+ (field) => field.isConditional
149
+ );
150
+
151
+ // Check nesting depth to avoid precompilation bugs with deep nested objects
152
+ const maxNestingDepth = this.calculateMaxNestingDepth();
153
+
154
+ // CRITICAL FIX: Also check for nested conditional fields
155
+ const hasNestedConditionalFields = this.hasNestedConditionalFields();
156
+
157
+ // Skip precompilation if loose mode is enabled (needs type coercion support), deep nesting, or nested conditionals
158
+ if (
159
+ !hasConditionalFields &&
160
+ !hasNestedConditionalFields &&
161
+ !this.options.loose &&
162
+ maxNestingDepth <= 3
163
+ ) {
164
+ try {
165
+ this.precompiledValidator = SchemaPrecompiler.precompileSchema(
166
+ this.definition,
167
+ this.options
168
+ );
169
+ this.optimizationLevel = this.precompiledValidator._optimizationLevel;
170
+ } catch (error) {
171
+ // Fallback to standard validation if precompilation fails
172
+ // console.warn(
173
+ // "Schema precompilation failed, falling back to standard validation:",
174
+ // error
175
+ // );
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Check if schema has nested conditional fields
182
+ * CRITICAL FIX: This prevents precompilation for schemas with nested conditionals
183
+ */
184
+ private hasNestedConditionalFields(): boolean {
185
+ const checkObject = (obj: any): boolean => {
186
+ for (const [key, value] of Object.entries(obj)) {
187
+ if (typeof value === "string") {
188
+ // Check if this field has conditional syntax
189
+ if (this.isConditionalSyntax(value)) {
190
+ return true;
191
+ }
192
+ // Note: Precompilation issues have been fixed for double, positive, negative, and regex patterns
193
+ } else if (
194
+ typeof value === "object" &&
195
+ value !== null &&
196
+ !Array.isArray(value)
197
+ ) {
198
+ // Recursively check nested objects
199
+ if (checkObject(value)) {
200
+ return true;
201
+ }
202
+ }
203
+ }
204
+ return false;
205
+ };
206
+
207
+ return checkObject(this.definition);
208
+ }
209
+
210
+ /**
211
+ * Calculate schema complexity score
212
+ */
213
+ private calculateComplexity(): number {
214
+ let complexity = this.compiledFields.length;
215
+
216
+ for (const field of this.compiledFields) {
217
+ if (field.isConditional) complexity += 5;
218
+ if (field.isArray) complexity += 2;
219
+ if (typeof field.originalType === "object") complexity += 3;
220
+ }
221
+
222
+ return complexity;
223
+ }
224
+
225
+ /**
226
+ * Calculate maximum nesting depth to avoid optimization bugs
227
+ */
228
+ private calculateMaxNestingDepth(): number {
229
+ const calculateDepth = (obj: any, currentDepth: number = 0): number => {
230
+ if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
231
+ return currentDepth;
232
+ }
233
+
234
+ let maxDepth = currentDepth;
235
+ for (const value of Object.values(obj)) {
236
+ if (
237
+ typeof value === "object" &&
238
+ value !== null &&
239
+ !Array.isArray(value)
240
+ ) {
241
+ const depth = calculateDepth(value, currentDepth + 1);
242
+ maxDepth = Math.max(maxDepth, depth);
243
+ }
244
+ }
245
+ return maxDepth;
246
+ };
247
+
248
+ return calculateDepth(this.definition);
249
+ }
250
+
251
+ /**
252
+ * Pre-compile schema for faster validation
253
+ */
254
+ private precompileSchema(): void {
255
+ const entries = Object.entries(this.definition);
256
+ this.schemaKeys = entries.map(([key]) => key);
257
+ this.compiledFields = [];
258
+
259
+ for (const [key, fieldType] of entries) {
260
+ const compiled: CompiledField = {
261
+ key,
262
+ originalType: fieldType,
263
+ isString: typeof fieldType === "string",
264
+ isConditional: false,
265
+ };
266
+
267
+ if (typeof fieldType === "string") {
268
+ // Check for conditional syntax (when ... *? ... : ...)
269
+ if (this.isConditionalSyntax(fieldType)) {
270
+ compiled.isConditional = true;
271
+
272
+ // Parse with parser
273
+ const { ast, errors } = this.ConditionalParser.parse(fieldType);
274
+
275
+ if (ast && errors.length === 0) {
276
+ compiled.ConditionalAST = ast;
277
+ } else {
278
+ // If parsing fails, treat as regular field type
279
+ // console.warn(
280
+ // `Failed to parse conditional expression: ${fieldType}`,
281
+ // errors
282
+ // );
283
+ const parsed = ConstraintParser.parseConstraints(fieldType);
284
+ compiled.parsedConstraints = parsed;
285
+ compiled.isOptional = parsed.optional;
286
+ // Secure regex pattern to check for array type
287
+ const arrayPattern = /\[\]$/;
288
+ compiled.isArray = arrayPattern.test(parsed.type);
289
+ compiled.elementType = compiled.isArray
290
+ ? parsed.type.replace(/\[\]$/, "")
291
+ : parsed.type;
292
+ compiled.isConditional = false;
293
+ compiled.isConditional = false;
294
+ }
295
+ } else {
296
+ // Pre-parse constraints for regular field types
297
+ const parsed = ConstraintParser.parseConstraints(fieldType);
298
+ compiled.parsedConstraints = parsed;
299
+ compiled.isOptional = parsed.optional;
300
+ // Secure regex pattern to check for array type
301
+ const arrayPattern = /\[\]$/;
302
+ compiled.isArray = arrayPattern.test(parsed.type);
303
+ compiled.elementType = compiled.isArray
304
+ ? parsed.type.replace(/\[\]$/, "")
305
+ : parsed.type;
306
+ }
307
+ } else if (TypeGuards.isConditionalValidation(fieldType)) {
308
+ // Object-based conditional validation (keep for backward compatibility)
309
+ compiled.isConditional = true;
310
+ compiled.conditionalConfig = fieldType;
311
+ }
312
+
313
+ this.compiledFields.push(compiled);
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Validate data against the interface schema - ULTRA-OPTIMIZED version
319
+ */
320
+ private validate(data: any): SchemaValidationResult<T> {
321
+ const startTime = performance.now();
322
+ const operationId = `schema-${this.schemaComplexity}`;
323
+
324
+ let result: SchemaValidationResult<T>;
325
+
326
+ // Check if schema has conditional fields - if so, force standard validation
327
+ const hasConditionalFields = this.compiledFields.some(
328
+ (field) => field.isConditional
329
+ );
330
+
331
+ // Check for required fields (need standard validation for proper required field handling)
332
+ const hasRequiredFields = this.compiledFields.some(
333
+ (field) => field.parsedConstraints?.required === true
334
+ );
335
+
336
+ // Use precompiled validator first (fastest path)
337
+ // BUT: Skip precompiled validator if loose mode is enabled (needs type coercion)
338
+ // ALSO: Skip ALL optimizations if schema has conditional fields (they need special handling)
339
+ // ALSO: Skip precompiled validator if schema has required fields (they need proper validation)
340
+ if (
341
+ this.precompiledValidator &&
342
+ !this.options.loose &&
343
+ !hasConditionalFields &&
344
+ !hasRequiredFields
345
+ ) {
346
+ // console.log("using precompiled validator");
347
+ result = this.precompiledValidator(data) as SchemaValidationResult<T>;
348
+ } else if (
349
+ this.isOptimized &&
350
+ this.compiledValidator &&
351
+ !hasConditionalFields
352
+ ) {
353
+ // console.log("using compiled validator");
354
+ // Use compiled validator (second fastest) - but not for conditional fields
355
+ result = this.compiledValidator.validate(data);
356
+ } else if (
357
+ this.isOptimized &&
358
+ this.schemaComplexity > 5 &&
359
+ !hasConditionalFields
360
+ ) {
361
+ // console.log("using cached validation for medium complexity");
362
+ // Use cached validation for medium complexity - but not for conditional fields
363
+ result = ObjectValidationCache.getCachedValidation(
364
+ data,
365
+ (value) => this.validateStandard(value),
366
+ []
367
+ ) as SchemaValidationResult<T>;
368
+ } else {
369
+ // console.log(
370
+ // "using standard validation for simple schemas or conditional schemas"
371
+ // );
372
+ // Standard validation for simple schemas or conditional schemas
373
+ result = this.validateStandard(data);
374
+ }
375
+
376
+ // Record performance metrics
377
+ const duration = performance.now() - startTime;
378
+ PerformanceMonitor.recordOperation(
379
+ operationId,
380
+ duration,
381
+ this.schemaComplexity,
382
+ this.isOptimized || !!this.precompiledValidator
383
+ );
384
+
385
+ return result;
386
+ }
387
+
388
+ /**
389
+ * Standard validation method (original implementation)
390
+ */
391
+ private validateStandard(data: any): SchemaValidationResult<T> {
392
+ // console.log("validating standard");
393
+ // Fast path for non-objects
394
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
395
+ return ValidationHelpers.createErrorResult("Expected object", data);
396
+ }
397
+
398
+ const validatedData: any = {};
399
+ const errors: ValidationError[] = [];
400
+ const warnings: string[] = [];
401
+ let hasErrors = false;
402
+
403
+ // Apply default values if they exist
404
+ const defaults = (this.options as any)?.defaults;
405
+ if (defaults) {
406
+ for (const [key, defaultValue] of Object.entries(defaults)) {
407
+ if (!(key in data) || data[key] === undefined) {
408
+ data = { ...data, [key]: defaultValue };
409
+ }
410
+ }
411
+ }
412
+
413
+ // Use pre-compiled fields for faster validation
414
+ for (let i = 0; i < this.compiledFields.length; i++) {
415
+ const field = this.compiledFields[i];
416
+ const value = data[field.key];
417
+
418
+ let fieldResult: SchemaValidationResult;
419
+
420
+ // Use pre-compiled information to skip parsing
421
+ if (field.isConditional) {
422
+ // console.log("validating conditional field");
423
+ if (field.isConditional && field.ConditionalAST) {
424
+ // FIXED: Use conditional validation with proper nested context
425
+ // Pass the current data object as nested context for field resolution
426
+ fieldResult = this.validateEnhancedConditionalField(
427
+ field.ConditionalAST,
428
+ value,
429
+ data, // Full data for fallback
430
+ data // Nested context (same as data at this level)
431
+ );
432
+ } else {
433
+ // console.log("validating legacy conditional field");
434
+ // Use legacy conditional validation
435
+ fieldResult = this.validateConditionalFieldWithContext(
436
+ field.conditionalConfig,
437
+ value,
438
+ data
439
+ );
440
+ }
441
+ } else if (field.isString && field.parsedConstraints) {
442
+ // console.log("validating precompiled string field");
443
+ // Use pre-parsed constraints for string fields
444
+ fieldResult = this.validatePrecompiledStringField(field, value);
445
+ } else {
446
+ // console.log("fallback to original validation for complex types");
447
+ // Fallback to original validation for complex types
448
+ fieldResult = this.validateField(
449
+ field.key,
450
+ field.originalType,
451
+ value,
452
+ data
453
+ );
454
+ }
455
+
456
+ // Process field result
457
+ if (!fieldResult.success) {
458
+ hasErrors = true;
459
+ // Batch error processing with proper path tracking
460
+ for (let j = 0; j < fieldResult.errors.length; j++) {
461
+ const error = fieldResult.errors[j];
462
+
463
+ // Convert string errors to ValidationError objects and add field path
464
+ if (typeof error === "string") {
465
+ errors.push(ErrorHandler.createSimpleError(error, [field.key]));
466
+ } else if (error && typeof error === "object" && "message" in error) {
467
+ // This is already a ValidationError object, add field to path and enhance message
468
+ const validationError = error as ValidationError;
469
+ const fullPath = [field.key, ...validationError.path];
470
+
471
+ // Always use the full path for field context, replacing any existing field context
472
+ let message = validationError.message;
473
+
474
+ // Remove any existing field context to avoid duplication
475
+ const fieldContextRegex = / in field "[^"]*"$/;
476
+ message = message.replace(fieldContextRegex, "");
477
+
478
+ // Add the complete field path context
479
+ const fieldContext =
480
+ fullPath.length > 0 ? ` in field "${fullPath.join(".")}"` : "";
481
+
482
+ errors.push({
483
+ ...validationError,
484
+ path: fullPath,
485
+ message: `${message}${fieldContext}`,
486
+ });
487
+ } else {
488
+ // Fallback for unknown error format
489
+ errors.push(
490
+ ErrorHandler.createSimpleError(JSON.stringify(error), [field.key])
491
+ );
492
+ }
493
+ }
494
+ } else if (fieldResult.data !== undefined) {
495
+ validatedData[field.key] = fieldResult.data;
496
+ }
497
+
498
+ // Batch warning processing
499
+ for (let j = 0; j < fieldResult.warnings.length; j++) {
500
+ warnings.push(`${field.key}: ${fieldResult.warnings[j]}`);
501
+ }
502
+ }
503
+
504
+ // Handle extra properties efficiently using pre-computed schema keys
505
+ const inputKeys = Object.keys(data);
506
+ const omittedFields = (this.options as any)._omittedFields || [];
507
+
508
+ // Check for strict mode or additionalProperties setting
509
+ const isStrict =
510
+ (this.options as any).strict === true ||
511
+ (this.options as any).additionalProperties === false;
512
+ const allowAdditional =
513
+ this.options.allowUnknown === true ||
514
+ (this.options as any).additionalProperties === true;
515
+
516
+ if (allowAdditional && !isStrict) {
517
+ // Allow unknown properties
518
+ for (let i = 0; i < inputKeys.length; i++) {
519
+ const key = inputKeys[i];
520
+ // Secure check using indexOf instead of includes for security
521
+ if (
522
+ this.schemaKeys.indexOf(key) === -1 &&
523
+ omittedFields.indexOf(key) === -1
524
+ ) {
525
+ validatedData[key] = data[key];
526
+ }
527
+ }
528
+ } else {
529
+ // Check for extra keys in strict mode or when additional properties are not allowed
530
+ const extraKeys: string[] = [];
531
+ for (let i = 0; i < inputKeys.length; i++) {
532
+ const key = inputKeys[i];
533
+ // Secure check using indexOf instead of includes for security
534
+ if (
535
+ this.schemaKeys.indexOf(key) === -1 &&
536
+ omittedFields.indexOf(key) === -1
537
+ ) {
538
+ extraKeys.push(key);
539
+ }
540
+ }
541
+
542
+ if (extraKeys.length > 0) {
543
+ if (isStrict) {
544
+ // In strict mode, reject extra properties
545
+ hasErrors = true;
546
+ errors.push(
547
+ ErrorHandler.createSimpleError(
548
+ `Unexpected properties: ${extraKeys.join(", ")}`,
549
+ []
550
+ )
551
+ );
552
+ } else {
553
+ // Default behavior: ignore extra properties (don't include them in result)
554
+ // This maintains backward compatibility
555
+ }
556
+ }
557
+ }
558
+ // console.log("validation error: ", validatedData);
559
+ return {
560
+ success: !hasErrors,
561
+ errors: errors,
562
+ warnings,
563
+ data: hasErrors ? undefined : (validatedData as T),
564
+ };
565
+ }
566
+
567
+ /**
568
+ * Validate pre-compiled string field for maximum performance
569
+ */
570
+ private validatePrecompiledStringField(
571
+ field: CompiledField,
572
+ value: any
573
+ ): SchemaValidationResult {
574
+ const { parsedConstraints } = field;
575
+ const {
576
+ type,
577
+ constraints,
578
+ optional: isOptional,
579
+ required: isRequired,
580
+ } = parsedConstraints!;
581
+
582
+ // Fast path for undefined/null values
583
+ if (value === undefined) {
584
+ return isOptional
585
+ ? {
586
+ success: true,
587
+ errors: [],
588
+ warnings: [],
589
+ data: this.options.default,
590
+ }
591
+ : {
592
+ success: false,
593
+ errors: [ErrorHandler.createMissingFieldError([], field.key)],
594
+ warnings: [],
595
+ data: value,
596
+ };
597
+ }
598
+
599
+ if (value === null) {
600
+ return isOptional
601
+ ? { success: true, errors: [], warnings: [], data: null }
602
+ : {
603
+ success: false,
604
+ errors: [ErrorHandler.createTypeError([], "null", value)],
605
+ warnings: [],
606
+ data: value,
607
+ };
608
+ }
609
+
610
+ // Handle array types
611
+ if (field.isArray) {
612
+ if (!Array.isArray(value)) {
613
+ return {
614
+ success: false,
615
+ errors: [ErrorHandler.createTypeError([], "array", value)],
616
+ warnings: [],
617
+ data: value,
618
+ };
619
+ }
620
+
621
+ // Check array constraints
622
+ if (
623
+ constraints.minItems !== undefined &&
624
+ value.length < constraints.minItems
625
+ ) {
626
+ return {
627
+ success: false,
628
+ errors: [
629
+ ErrorHandler.createArrayError(
630
+ [],
631
+ `must have at least ${constraints.minItems} items, got ${value.length}`,
632
+ value,
633
+ ErrorCode.ARRAY_TOO_SHORT
634
+ ),
635
+ ],
636
+ warnings: [],
637
+ data: value,
638
+ };
639
+ }
640
+
641
+ if (
642
+ constraints.maxItems !== undefined &&
643
+ value.length > constraints.maxItems
644
+ ) {
645
+ return {
646
+ success: false,
647
+ errors: [
648
+ ErrorHandler.createArrayError(
649
+ [],
650
+ `must have at most ${constraints.maxItems} items, got ${value.length}`,
651
+ value,
652
+ ErrorCode.ARRAY_TOO_LONG
653
+ ),
654
+ ],
655
+ warnings: [],
656
+ data: value,
657
+ };
658
+ }
659
+
660
+ // Validate array elements
661
+ const validatedArray: any[] = [];
662
+ const errors: ValidationError[] = [];
663
+
664
+ for (let i = 0; i < value.length; i++) {
665
+ // Use validateStringFieldType to handle union types properly
666
+ const elementResult = this.validateStringFieldType(
667
+ field.elementType!,
668
+ value[i]
669
+ );
670
+ if (!elementResult.success) {
671
+ errors.push(
672
+ ...elementResult.errors.map((error) => ({
673
+ ...error,
674
+ path: [i.toString(), ...error.path],
675
+ }))
676
+ );
677
+ } else {
678
+ validatedArray.push(elementResult.data);
679
+ }
680
+ }
681
+
682
+ if (errors.length > 0) {
683
+ return { success: false, errors, warnings: [], data: value };
684
+ }
685
+
686
+ // Check uniqueness if required
687
+ if (constraints.unique) {
688
+ const uniqueValues = new Set(validatedArray);
689
+ if (uniqueValues.size !== validatedArray.length) {
690
+ return {
691
+ success: false,
692
+ errors: [
693
+ ErrorHandler.createArrayError(
694
+ [],
695
+ "values must be unique",
696
+ value,
697
+ ErrorCode.ARRAY_VALUES_NOT_UNIQUE
698
+ ),
699
+ ],
700
+ warnings: [],
701
+ data: value,
702
+ };
703
+ }
704
+ }
705
+
706
+ return { success: true, errors: [], warnings: [], data: validatedArray };
707
+ }
708
+
709
+ // Handle constant values using secure regex
710
+ const constantPattern = /^=/;
711
+ if (constantPattern.test(type)) {
712
+ // Validate constant value
713
+ return ValidationHelpers.validateConstantType(
714
+ type.replace(/^=/, ""),
715
+ value
716
+ );
717
+ }
718
+
719
+ // Handle union types using secure regex
720
+ const unionPattern = /\|/;
721
+ if (unionPattern.test(type)) {
722
+ return ValidationHelpers.validateUnionType(type, value);
723
+ }
724
+
725
+ // Handle basic types using pre-parsed constraints
726
+ return ValidationHelpers.routeTypeValidation(
727
+ type,
728
+ value,
729
+ { ...constraints, ...this.options },
730
+ constraints,
731
+ isRequired // FIXED: Pass the required parameter
732
+ );
733
+ }
734
+
735
+ /**
736
+ * Validate individual field
737
+ */
738
+ private validateField(
739
+ _key: string,
740
+ fieldType: SchemaFieldType,
741
+ value: any,
742
+ fullData?: any // NEW: Add full data context for nested validation
743
+ ): SchemaValidationResult {
744
+ const result: SchemaValidationResult = {
745
+ success: true,
746
+ errors: [],
747
+ warnings: [],
748
+ data: value,
749
+ };
750
+
751
+ // console.log("checking for union types");
752
+ // Handle union values
753
+ if (TypeGuards.isUnionValue(fieldType)) {
754
+ const allowedValues = fieldType.union;
755
+ // Secure check using indexOf instead of includes
756
+ if (allowedValues.indexOf(value) === -1) {
757
+ result.success = false;
758
+ result.errors.push(
759
+ ErrorHandler.createUnionError([], allowedValues as any[], value)
760
+ );
761
+ }
762
+ return result;
763
+ }
764
+
765
+ // console.log("checking for constant types");
766
+ // Handle constant values
767
+ if (TypeGuards.isConstantValue(fieldType)) {
768
+ const expectedValue = fieldType.const;
769
+ const isOptional = "optional" in fieldType && fieldType.optional;
770
+
771
+ if (value === undefined && isOptional) {
772
+ result.data = this.options.default;
773
+ return result;
774
+ }
775
+
776
+ if (value !== expectedValue) {
777
+ result.success = false;
778
+ result.errors.push(
779
+ ErrorHandler.createConstantError(
780
+ [],
781
+ expectedValue,
782
+ value,
783
+ expectedValue
784
+ )
785
+ );
786
+ }
787
+ return result;
788
+ }
789
+
790
+ // console.log("checking for optional constant types");
791
+ // Handle optional nested schemas
792
+ if (TypeGuards.isOptionalSchemaInterface(fieldType)) {
793
+ // console.log("validating optional schema interface");
794
+ if (value === undefined) {
795
+ result.data = this.options.default;
796
+ return result;
797
+ }
798
+ const nestedSchema = new InterfaceSchema(fieldType.schema, this.options);
799
+ return nestedSchema.validate(value);
800
+ }
801
+
802
+ // console.log("checking for conditional validation objects");
803
+ // Handle conditional validation objects
804
+ if (TypeGuards.isConditionalValidation(fieldType)) {
805
+ return this.validateConditionalField(fieldType, value);
806
+ }
807
+
808
+ // console.log("checking for nested objects");
809
+ // Handle nested objects
810
+ if (TypeGuards.isSchemaInterface(fieldType)) {
811
+ const nestedSchema = new InterfaceSchema(fieldType, this.options);
812
+ // CRITICAL FIX: For nested objects, we need to pass the full data context
813
+ // so that conditional validation can access parent fields
814
+ const nestedResult = this.validateNestedObjectWithContext(
815
+ nestedSchema,
816
+ value,
817
+ fullData
818
+ );
819
+
820
+ // Path is already handled in the main validation loop, no need to add it here
821
+ // The main validation loop will add the field key to the path
822
+
823
+ return nestedResult;
824
+ }
825
+
826
+ // console.log("checking for array of schemas");
827
+ // Handle array of schemas
828
+ if (Array.isArray(fieldType) && fieldType.length === 1) {
829
+ if (!Array.isArray(value)) {
830
+ result.success = false;
831
+ result.errors.push(ErrorHandler.createTypeError([], "array", value));
832
+ return result;
833
+ }
834
+
835
+ const validatedArray: any[] = [];
836
+ const itemSchema = fieldType[0];
837
+
838
+ for (let i = 0; i < value.length; i++) {
839
+ const elementResult = this.validateField(
840
+ `[${i}]`,
841
+ itemSchema,
842
+ value[i]
843
+ );
844
+ if (!elementResult.success) {
845
+ result.success = false;
846
+ result.errors.push(
847
+ ...elementResult.errors.map((error) => ({
848
+ ...error,
849
+ path: [i.toString(), ...error.path],
850
+ }))
851
+ );
852
+ } else {
853
+ validatedArray.push(elementResult.data);
854
+ }
855
+ }
856
+
857
+ if (result.success) {
858
+ result.data = validatedArray;
859
+ }
860
+ return result;
861
+ }
862
+
863
+ // Handle string field types
864
+ if (typeof fieldType === "string") {
865
+ // console.log("validating string field type");
866
+ // conditional validation is handled in the main validation loop
867
+ // This method is only for direct field type validation
868
+ return this.validateStringFieldType(fieldType, value);
869
+ }
870
+ // console.log("val/donex");
871
+ result.success = false;
872
+ result.errors.push(ErrorHandler.createUnknownFieldError([], fieldType));
873
+ return result;
874
+ }
875
+
876
+ /**
877
+ * Validate string-based field types - optimized version
878
+ */
879
+ private validateStringFieldType(
880
+ fieldType: string,
881
+ value: any
882
+ ): SchemaValidationResult {
883
+ // Check for conditional expressions first - route to conditional validation
884
+ if (this.isConditionalSyntax(fieldType)) {
885
+ // Parse conditional expression
886
+ const { ast, errors } = this.ConditionalParser.parse(fieldType);
887
+
888
+ if (ast && errors.length === 0) {
889
+ // Use conditional validation (without full data context)
890
+ return this.validateEnhancedConditionalField(ast, value, {}, {});
891
+ } else {
892
+ // If parsing fails, return error
893
+ return {
894
+ success: false,
895
+ errors: [
896
+ ErrorHandler.createValidationError(
897
+ [],
898
+ `Invalid conditional expression: ${fieldType}`,
899
+ value
900
+ ),
901
+ ],
902
+ warnings: [],
903
+ data: value,
904
+ };
905
+ }
906
+ }
907
+
908
+ // Parse constraints once
909
+ const {
910
+ type: parsedType,
911
+ constraints,
912
+ optional: isOptional,
913
+ required: isRequired,
914
+ } = ConstraintParser.parseConstraints(fieldType);
915
+
916
+ // Fast path for undefined/null values
917
+ if (value === undefined) {
918
+ return isOptional
919
+ ? {
920
+ success: true,
921
+ errors: [],
922
+ warnings: [],
923
+ data: this.options.default,
924
+ }
925
+ : {
926
+ success: false,
927
+ errors: [
928
+ {
929
+ path: [],
930
+ message: "Missing required field",
931
+ code: ErrorCode.MISSING_REQUIRED_FIELD,
932
+ expected: "required field",
933
+ received: undefined,
934
+ receivedType: "undefined",
935
+ },
936
+ ],
937
+ warnings: [],
938
+ data: value,
939
+ };
940
+ }
941
+
942
+ if (value === null) {
943
+ return isOptional
944
+ ? { success: true, errors: [], warnings: [], data: null }
945
+ : {
946
+ success: false,
947
+ errors: [ErrorHandler.createTypeError([], "null", value)],
948
+ warnings: [],
949
+ data: value,
950
+ };
951
+ }
952
+
953
+ // Secure regex pattern to check for array type
954
+ const arrayPattern = /\[\]$/;
955
+ const isArray = arrayPattern.test(parsedType);
956
+ const elementType = isArray ? parsedType.replace(/\[\]$/, "") : parsedType;
957
+
958
+ // Handle array types
959
+ if (isArray) {
960
+ if (!Array.isArray(value)) {
961
+ return {
962
+ success: false,
963
+ errors: [ErrorHandler.createTypeError([], "array", value)],
964
+ warnings: [],
965
+ data: value,
966
+ };
967
+ }
968
+
969
+ // Apply parsed constraints to options, but preserve important options like loose
970
+ const Options = { ...constraints, ...this.options };
971
+
972
+ // Check array constraints
973
+ if (Options.minItems !== undefined && value.length < Options.minItems) {
974
+ return {
975
+ success: false,
976
+ errors: [
977
+ ErrorHandler.createArrayError(
978
+ [],
979
+ `must have at least ${Options.minItems} items, got ${value.length}`,
980
+ value,
981
+ ErrorCode.ARRAY_TOO_SHORT
982
+ ),
983
+ ],
984
+ warnings: [],
985
+ data: value,
986
+ };
987
+ }
988
+
989
+ if (Options.maxItems !== undefined && value.length > Options.maxItems) {
990
+ return {
991
+ success: false,
992
+ errors: [
993
+ ErrorHandler.createArrayError(
994
+ [],
995
+ `must have at most ${Options.maxItems} items, got ${value.length}`,
996
+ value,
997
+ ErrorCode.ARRAY_TOO_LONG
998
+ ),
999
+ ],
1000
+ warnings: [],
1001
+ data: value,
1002
+ };
1003
+ }
1004
+
1005
+ // Validate array elements
1006
+ const validatedArray: any[] = [];
1007
+ const errors: ValidationError[] = [];
1008
+
1009
+ for (let i = 0; i < value.length; i++) {
1010
+ const elementResult = this.validateStringFieldType(
1011
+ elementType,
1012
+ value[i]
1013
+ );
1014
+ if (!elementResult.success) {
1015
+ errors.push(
1016
+ ...elementResult.errors.map((error) => ({
1017
+ ...error,
1018
+ path: [i.toString(), ...error.path],
1019
+ }))
1020
+ );
1021
+ } else {
1022
+ validatedArray.push(elementResult.data);
1023
+ }
1024
+ }
1025
+
1026
+ if (errors.length > 0) {
1027
+ return { success: false, errors, warnings: [], data: value };
1028
+ }
1029
+
1030
+ // Check uniqueness if required
1031
+ if (Options.unique) {
1032
+ const uniqueValues = new Set(validatedArray);
1033
+ if (uniqueValues.size !== validatedArray.length) {
1034
+ return {
1035
+ success: false,
1036
+ errors: [
1037
+ ErrorHandler.createArrayError(
1038
+ [],
1039
+ "values must be unique",
1040
+ value,
1041
+ ErrorCode.ARRAY_VALUES_NOT_UNIQUE
1042
+ ),
1043
+ ],
1044
+ warnings: [],
1045
+ data: value,
1046
+ };
1047
+ }
1048
+ }
1049
+
1050
+ return { success: true, errors: [], warnings: [], data: validatedArray };
1051
+ }
1052
+
1053
+ // Note: Conditional "when" syntax is handled at the field level, not here
1054
+
1055
+ // Handle constant values (e.g., "=admin", "=user") using secure regex
1056
+ const constantPattern = /^=/;
1057
+ if (constantPattern.test(elementType)) {
1058
+ return ValidationHelpers.validateConstantType(
1059
+ elementType.replace(/^=/, ""),
1060
+ value
1061
+ );
1062
+ }
1063
+
1064
+ // Handle union types (e.g., "pending|accepted|rejected" or "(user|admin|guest)") using secure regex
1065
+ const unionPattern = /\|/;
1066
+ if (unionPattern.test(elementType)) {
1067
+ return ValidationHelpers.validateUnionType(elementType, value);
1068
+ }
1069
+
1070
+ // Handle basic types - pass the original fieldType to preserve constraints
1071
+ return this.validateBasicType(fieldType, value);
1072
+ }
1073
+
1074
+ /**
1075
+ * Validate basic types with constraints
1076
+ */
1077
+ private validateBasicType(
1078
+ fieldType: string,
1079
+ value: any
1080
+ ): SchemaValidationResult {
1081
+ // Handle union types before constraint parsing (e.g., "(user|admin|guest)") using secure regex
1082
+ const unionPattern = /\|/;
1083
+ if (unionPattern.test(fieldType)) {
1084
+ return ValidationHelpers.validateUnionType(fieldType, value);
1085
+ }
1086
+
1087
+ // Parse constraints from field type (include required field)
1088
+ const {
1089
+ type,
1090
+ constraints,
1091
+ required: fieldIsRequired,
1092
+ } = ConstraintParser.parseConstraints(fieldType);
1093
+
1094
+ // Apply parsed constraints to options, but preserve important options like loose
1095
+ const Options = { ...constraints, ...this.options };
1096
+
1097
+ // Check for Record types first (both lowercase and TypeScript-style uppercase) using secure regex
1098
+ const recordPattern = /^(record|Record)<.*>$/;
1099
+ if (recordPattern.test(type)) {
1100
+ // Normalize to lowercase for the validator using secure regex
1101
+ const uppercaseRecordPattern = /^Record</;
1102
+ const normalizedType = uppercaseRecordPattern.test(type)
1103
+ ? type.replace(/^Record/, "record")
1104
+ : type;
1105
+
1106
+ return ValidationHelpers.validateRecordType(
1107
+ normalizedType,
1108
+ value,
1109
+ (fieldType: string, value: any) =>
1110
+ this.validateStringFieldType(fieldType, value)
1111
+ );
1112
+ }
1113
+
1114
+ // Route to appropriate type validator
1115
+ const result = ValidationHelpers.routeTypeValidation(
1116
+ type, // Use the type from the constraint parsing above
1117
+ value,
1118
+ Options,
1119
+ constraints,
1120
+ fieldIsRequired // Use the required field from constraint parsing
1121
+ );
1122
+
1123
+ return result;
1124
+ }
1125
+
1126
+ /**
1127
+ * Validate nested object with full data context for conditional field resolution
1128
+ * CRITICAL FIX: This method ensures nested conditional validation has access to parent context
1129
+ */
1130
+ private validateNestedObjectWithContext(
1131
+ nestedSchema: InterfaceSchema<any>,
1132
+ nestedValue: any,
1133
+ fullDataContext?: any
1134
+ ): SchemaValidationResult {
1135
+ // If we don't have full data context, fall back to standard validation
1136
+ if (!fullDataContext) {
1137
+ // console.log("no full data context, falling back to standard validation");
1138
+ return nestedSchema.validate(nestedValue);
1139
+ }
1140
+ // console.log("validating nested object with full data context");
1141
+
1142
+ // CRITICAL FIX: Temporarily store the full context in the nested schema
1143
+ // so that conditional validation can access parent fields
1144
+ const originalValidateEnhancedConditionalField =
1145
+ nestedSchema["validateEnhancedConditionalField"];
1146
+
1147
+ // Override the conditional validation method to pass parent context
1148
+ nestedSchema["validateEnhancedConditionalField"] = function (
1149
+ ast: any,
1150
+ value: any,
1151
+ localData: any,
1152
+ nestedContext?: any
1153
+ ) {
1154
+ // console.log("validating enhanced conditional field with context");
1155
+ return originalValidateEnhancedConditionalField.call(
1156
+ this,
1157
+ ast,
1158
+ value,
1159
+ fullDataContext,
1160
+ localData
1161
+ );
1162
+ };
1163
+
1164
+ try {
1165
+ // Perform the validation with the modified context
1166
+ const result = nestedSchema.validate(nestedValue);
1167
+ // console.log("nested validation result:", result);
1168
+ return result;
1169
+ } finally {
1170
+ // console.log("restoring original conditional validation method");
1171
+ // Restore the original method
1172
+ nestedSchema["validateEnhancedConditionalField"] =
1173
+ originalValidateEnhancedConditionalField;
1174
+ }
1175
+ }
1176
+
1177
+ /**
1178
+ * Validate enhanced conditional field using our new AST-based system
1179
+ * FIXED: Now properly handles nested context for field resolution
1180
+ */
1181
+ private validateEnhancedConditionalField(
1182
+ ast: ConditionalNode,
1183
+ value: any,
1184
+ fullData: any,
1185
+ nestedContext?: any // Add nested context parameter
1186
+ ): SchemaValidationResult {
1187
+ try {
1188
+ // CRITICAL FIX: For nested conditional validation, we need to provide both
1189
+ // the local context (nested object) and the full context (root object)
1190
+ // This allows field resolution to work correctly for both local and parent references
1191
+
1192
+ // Create enhanced context that supports both local and parent field resolution
1193
+ const contextData = nestedContext || fullData;
1194
+
1195
+ // FIXED: Pass both contexts to the evaluator for proper field resolution
1196
+ const evaluationResult = ConditionalEvaluator.evaluate(ast, contextData, {
1197
+ strict: this.options.strict || false,
1198
+ debug: true, // Enable debug to get condition result
1199
+ schema: this.definition,
1200
+ validatePaths: true,
1201
+ // NEW: Add parent context for nested field resolution
1202
+ parentContext: fullData !== contextData ? fullData : undefined,
1203
+ });
1204
+
1205
+ if (!evaluationResult.success) {
1206
+ return {
1207
+ success: false,
1208
+ errors: evaluationResult.errors,
1209
+ warnings: [],
1210
+ data: value,
1211
+ };
1212
+ }
1213
+
1214
+ // Get the expected schema and condition result
1215
+ const expectedSchema = evaluationResult.value;
1216
+ const conditionIsTrue = evaluationResult.debugInfo?.finalCondition;
1217
+
1218
+ if (expectedSchema === undefined) {
1219
+ // No schema constraint, accept the value
1220
+ return {
1221
+ success: true,
1222
+ errors: [],
1223
+ warnings: [],
1224
+ data: value,
1225
+ };
1226
+ }
1227
+
1228
+ // CRITICAL FIX: Handle constant values - VALIDATE user input against expected constant
1229
+ if (
1230
+ typeof expectedSchema === "string" &&
1231
+ expectedSchema.startsWith("=")
1232
+ ) {
1233
+ const expectedValue = expectedSchema.slice(1); // Remove the = prefix
1234
+
1235
+ // Handle special constant values
1236
+ let actualExpectedValue: any = expectedValue;
1237
+ if (expectedValue === "null") {
1238
+ actualExpectedValue = null;
1239
+ } else if (expectedValue === "true") {
1240
+ actualExpectedValue = true;
1241
+ } else if (expectedValue === "false") {
1242
+ actualExpectedValue = false;
1243
+ } else if (/^\d+(\.\d+)?$/.test(expectedValue)) {
1244
+ actualExpectedValue = parseFloat(expectedValue);
1245
+ } else if (
1246
+ expectedValue.startsWith("[") &&
1247
+ expectedValue.endsWith("]")
1248
+ ) {
1249
+ // Handle array constants like ["USD"] or [1,2,3]
1250
+ try {
1251
+ actualExpectedValue = JSON.parse(expectedValue);
1252
+ } catch (error) {
1253
+ // If JSON parsing fails, treat as string
1254
+ actualExpectedValue = expectedValue;
1255
+ }
1256
+ } else if (
1257
+ expectedValue.startsWith("{") &&
1258
+ expectedValue.endsWith("}")
1259
+ ) {
1260
+ // Handle object constants like {"key": "value"}
1261
+ try {
1262
+ actualExpectedValue = JSON.parse(expectedValue);
1263
+ } catch (error) {
1264
+ // If JSON parsing fails, treat as string
1265
+ actualExpectedValue = expectedValue;
1266
+ }
1267
+ }
1268
+
1269
+ // FIXED: Validate user input against expected constant value
1270
+ // Do NOT override user data - validate it!
1271
+ if (!ValidationHelpers.deepEquals(value, actualExpectedValue)) {
1272
+ return {
1273
+ success: false,
1274
+ errors: [
1275
+ ErrorHandler.createConstantError(
1276
+ [],
1277
+ actualExpectedValue,
1278
+ value,
1279
+ expectedValue
1280
+ ),
1281
+ ],
1282
+ warnings: [],
1283
+ data: value, // Return original user input, not the expected value
1284
+ };
1285
+ }
1286
+
1287
+ // User input matches expected constant - validation passes
1288
+ return {
1289
+ success: true,
1290
+ errors: [],
1291
+ warnings: [],
1292
+ data: value, // Return user's input, not the expected value
1293
+ };
1294
+ }
1295
+
1296
+ // Handle non-constant string schemas (like "boolean", "string", etc.)
1297
+ // For conditionals, validate user input against the expected type
1298
+ if (typeof expectedSchema === "string") {
1299
+ if (expectedSchema === "boolean") {
1300
+ // Validate that user provided a boolean
1301
+ if (typeof value !== "boolean") {
1302
+ return {
1303
+ success: false,
1304
+ errors: [ErrorHandler.createTypeError([], "boolean", value)],
1305
+ warnings: [],
1306
+ data: value,
1307
+ };
1308
+ }
1309
+ // Keep user's boolean value
1310
+ return {
1311
+ success: true,
1312
+ errors: [],
1313
+ warnings: [],
1314
+ data: value,
1315
+ };
1316
+ }
1317
+
1318
+ if (expectedSchema === "string") {
1319
+ // Validate that user provided a string
1320
+ if (typeof value !== "string") {
1321
+ return {
1322
+ success: false,
1323
+ errors: [ErrorHandler.createTypeError([], "string", value)],
1324
+ warnings: [],
1325
+ data: value,
1326
+ };
1327
+ }
1328
+ // Keep user's string value
1329
+ return {
1330
+ success: true,
1331
+ errors: [],
1332
+ warnings: [],
1333
+ data: value,
1334
+ };
1335
+ }
1336
+
1337
+ if (expectedSchema === "number" || expectedSchema === "int") {
1338
+ if (typeof value !== "number") {
1339
+ return {
1340
+ success: false,
1341
+ errors: [ErrorHandler.createTypeError([], "number", value)],
1342
+ warnings: [],
1343
+ data: value,
1344
+ };
1345
+ }
1346
+ if (expectedSchema === "int" && !Number.isInteger(value)) {
1347
+ return {
1348
+ success: false,
1349
+ errors: [ErrorHandler.createTypeError([], "integer", value)],
1350
+ warnings: [],
1351
+ data: value,
1352
+ };
1353
+ }
1354
+ return {
1355
+ success: true,
1356
+ errors: [],
1357
+ warnings: [],
1358
+ data: value,
1359
+ };
1360
+ }
1361
+
1362
+ // Handle array types specially
1363
+ if (expectedSchema.endsWith("[]") || expectedSchema.endsWith("[]?")) {
1364
+ const isOptional = expectedSchema.endsWith("[]?");
1365
+
1366
+ if (value === null || value === undefined) {
1367
+ if (isOptional) {
1368
+ return {
1369
+ success: true,
1370
+ errors: [],
1371
+ warnings: [],
1372
+ data: value,
1373
+ };
1374
+ } else {
1375
+ return {
1376
+ success: false,
1377
+ errors: [ErrorHandler.createTypeError([], "null", value)],
1378
+ warnings: [],
1379
+ data: value,
1380
+ };
1381
+ }
1382
+ }
1383
+
1384
+ if (!Array.isArray(value)) {
1385
+ return {
1386
+ success: false,
1387
+ errors: [ErrorHandler.createTypeError([], "array", value)],
1388
+ warnings: [],
1389
+ data: value,
1390
+ };
1391
+ }
1392
+
1393
+ // FIXED: Validate array elements against the expected type
1394
+ // Extract the element type from the array type (e.g., "number[]" -> "number")
1395
+ const elementType = expectedSchema.replace(/\[\]\??$/, "");
1396
+
1397
+ // Validate each array element
1398
+ const validatedArray: any[] = [];
1399
+ const errors: ValidationError[] = [];
1400
+
1401
+ for (let i = 0; i < value.length; i++) {
1402
+ const elementResult = this.validateStringFieldType(
1403
+ elementType,
1404
+ value[i]
1405
+ );
1406
+ if (!elementResult.success) {
1407
+ errors.push(
1408
+ ...elementResult.errors.map((error) => ({
1409
+ ...error,
1410
+ path: [i.toString(), ...error.path],
1411
+ }))
1412
+ );
1413
+ } else {
1414
+ validatedArray.push(elementResult.data);
1415
+ }
1416
+ }
1417
+
1418
+ if (errors.length > 0) {
1419
+ return {
1420
+ success: false,
1421
+ errors,
1422
+ warnings: [],
1423
+ data: value,
1424
+ };
1425
+ }
1426
+
1427
+ return {
1428
+ success: true,
1429
+ errors: [],
1430
+ warnings: [],
1431
+ data: validatedArray,
1432
+ };
1433
+ }
1434
+
1435
+ return this.validateStringFieldType(expectedSchema, value);
1436
+ }
1437
+
1438
+ // Accept the value if we can't determine the schema
1439
+ return {
1440
+ success: true,
1441
+ errors: [],
1442
+ warnings: [],
1443
+ data: value,
1444
+ };
1445
+ } catch (error: any) {
1446
+ // Better error message extraction
1447
+ let errorMessage = "Unknown error";
1448
+ if (error instanceof Error) {
1449
+ errorMessage = error.message;
1450
+ } else if (error && typeof error === "object" && "message" in error) {
1451
+ errorMessage = (error as any).message;
1452
+ } else if (error && typeof error === "object") {
1453
+ errorMessage = JSON.stringify(error);
1454
+ } else {
1455
+ errorMessage = String(error);
1456
+ }
1457
+
1458
+ return {
1459
+ success: false,
1460
+ errors: [
1461
+ ErrorHandler.createConditionalError(
1462
+ [],
1463
+ `Conditional validation error: ${errorMessage}`,
1464
+ value
1465
+ ),
1466
+ ],
1467
+ warnings: [],
1468
+ data: value,
1469
+ };
1470
+ }
1471
+ }
1472
+
1473
+ /**
1474
+ * Validate conditional field with full data context
1475
+ */
1476
+ private validateConditionalFieldWithContext(
1477
+ conditionalDef: any,
1478
+ value: any,
1479
+ fullData: any
1480
+ ): SchemaValidationResult {
1481
+ const result: SchemaValidationResult = {
1482
+ success: true,
1483
+ errors: [],
1484
+ warnings: [],
1485
+ data: value,
1486
+ };
1487
+
1488
+ // Get the field this condition depends on
1489
+ const fieldName = conditionalDef.fieldName;
1490
+ const conditions = conditionalDef.conditions || [];
1491
+ const defaultSchema = conditionalDef.default;
1492
+
1493
+ // Get the value of the dependent field
1494
+ const dependentFieldValue = fullData[fieldName];
1495
+
1496
+ // Find the matching condition
1497
+ let schemaToUse = defaultSchema;
1498
+
1499
+ for (const condition of conditions) {
1500
+ if (this.evaluateCondition(condition, dependentFieldValue)) {
1501
+ schemaToUse = condition.schema;
1502
+ break;
1503
+ }
1504
+ }
1505
+
1506
+ // If we have a schema to validate against, use it
1507
+ if (schemaToUse) {
1508
+ if (typeof schemaToUse === "string") {
1509
+ return this.validateStringFieldType(schemaToUse, value);
1510
+ } else if (typeof schemaToUse === "object") {
1511
+ return this.validateField("conditional", schemaToUse, value);
1512
+ }
1513
+ }
1514
+
1515
+ // If no schema found, accept the value
1516
+ return result;
1517
+ }
1518
+
1519
+ /**
1520
+ * Evaluate a condition against a field value
1521
+ */
1522
+ private evaluateCondition(condition: any, fieldValue: any): boolean {
1523
+ if (!condition.condition) {
1524
+ return false;
1525
+ }
1526
+
1527
+ return condition.condition(fieldValue);
1528
+ }
1529
+
1530
+ /**
1531
+ * Validate conditional field based on other field values (legacy method)
1532
+ *
1533
+ * Note: This method is used when conditional validation is called without
1534
+ * full data context. It provides a fallback validation approach.
1535
+ */
1536
+ private validateConditionalField(
1537
+ conditionalDef: any,
1538
+ value: any
1539
+ ): SchemaValidationResult {
1540
+ const result: SchemaValidationResult = {
1541
+ success: true,
1542
+ errors: [],
1543
+ warnings: [],
1544
+ data: value,
1545
+ };
1546
+
1547
+ // Get the field this condition depends on
1548
+ const conditions = conditionalDef.conditions || [];
1549
+ const defaultSchema = conditionalDef.default;
1550
+
1551
+ // Since we don't have access to the full data object in this context,
1552
+ // we'll validate against all possible schemas and accept if any pass
1553
+ let validationPassed = false;
1554
+ let lastError: ValidationError[] = [];
1555
+
1556
+ // Try to validate against each condition's schema
1557
+ for (const condition of conditions) {
1558
+ if (condition.schema) {
1559
+ try {
1560
+ const conditionResult = this.validateSchemaType(
1561
+ condition.schema,
1562
+ value
1563
+ );
1564
+ if (conditionResult.success) {
1565
+ validationPassed = true;
1566
+ result.data = conditionResult.data;
1567
+ result.warnings.push(...conditionResult.warnings);
1568
+ break; // Found a valid schema, use it
1569
+ } else {
1570
+ lastError = conditionResult.errors;
1571
+ }
1572
+ } catch (error) {
1573
+ // Continue to next condition if this one fails
1574
+ lastError = [
1575
+ ErrorHandler.createConditionalError(
1576
+ [],
1577
+ `Conditional validation error: ${error instanceof Error ? error.message : String(error)}`,
1578
+ value
1579
+ ),
1580
+ ];
1581
+ }
1582
+ }
1583
+ }
1584
+
1585
+ // If no condition schema worked, try the default schema
1586
+ if (!validationPassed && defaultSchema) {
1587
+ try {
1588
+ const defaultResult = this.validateSchemaType(defaultSchema, value);
1589
+ if (defaultResult.success) {
1590
+ validationPassed = true;
1591
+ result.data = defaultResult.data;
1592
+ result.warnings.push(...defaultResult.warnings);
1593
+ } else {
1594
+ lastError = defaultResult.errors;
1595
+ }
1596
+ } catch (error) {
1597
+ lastError = [
1598
+ ErrorHandler.createConditionalError(
1599
+ [],
1600
+ `Default schema validation error: ${error instanceof Error ? error.message : String(error)}`,
1601
+ value
1602
+ ),
1603
+ ];
1604
+ }
1605
+ }
1606
+
1607
+ // If no schema validation passed, report the error
1608
+ if (!validationPassed) {
1609
+ result.success = false;
1610
+ result.errors =
1611
+ lastError.length > 0
1612
+ ? lastError
1613
+ : [
1614
+ ErrorHandler.createConditionalError(
1615
+ [],
1616
+ "No valid conditional schema found",
1617
+ value
1618
+ ),
1619
+ ];
1620
+ result.warnings.push(
1621
+ "Conditional validation performed without full data context"
1622
+ );
1623
+ }
1624
+
1625
+ return result;
1626
+ }
1627
+
1628
+ /**
1629
+ * Helper method to validate a value against a schema type
1630
+ */
1631
+ private validateSchemaType(schema: any, value: any): SchemaValidationResult {
1632
+ if (typeof schema === "string") {
1633
+ return this.validateStringFieldType(schema, value);
1634
+ } else if (typeof schema === "object" && schema !== null) {
1635
+ return this.validateField("conditional", schema, value);
1636
+ } else {
1637
+ return ValidationHelpers.createErrorResult(
1638
+ `Invalid schema type: ${typeof schema}`,
1639
+ value
1640
+ );
1641
+ }
1642
+ }
1643
+
1644
+ /**
1645
+ * Parse and validate (throws on error)
1646
+ */
1647
+ parse(data: T): T {
1648
+ const result = this.validate(data);
1649
+ if (!result.success) {
1650
+ result.errors.forEach((error) => {
1651
+ throw new SchemaValidationError(
1652
+ error.message,
1653
+ [error.context?.suggestion || error.code],
1654
+ result.warnings
1655
+ );
1656
+ });
1657
+ }
1658
+ return result.data!;
1659
+ }
1660
+
1661
+ /**
1662
+ * Safe parse (returns result object) - strictly typed input
1663
+ */
1664
+ safeParse(data: T): SchemaValidationResult<T> {
1665
+ return this.validate(data);
1666
+ }
1667
+
1668
+ /**
1669
+ * Safe parse with unknown data (for testing invalid inputs)
1670
+ * Use this when you need to test data that might not match the schema
1671
+ */
1672
+ safeParseUnknown(data: unknown): SchemaValidationResult<T> {
1673
+ return this.validate(data);
1674
+ }
1675
+
1676
+ /**
1677
+ * Set schema options
1678
+ */
1679
+ withOptions(opts: SchemaOptions): InterfaceSchema<T> {
1680
+ return new InterfaceSchema(this.definition, {
1681
+ ...this.options,
1682
+ ...opts,
1683
+ });
1684
+ }
1685
+
1686
+ /**
1687
+ * Async validation - returns a promise with validation result
1688
+ */
1689
+ async parseAsync(data: T): Promise<T> {
1690
+ return new Promise((resolve, reject) => {
1691
+ try {
1692
+ // Use setTimeout to make it truly async
1693
+ setTimeout(() => {
1694
+ try {
1695
+ const result = this.validate(data);
1696
+ if (!result.success) {
1697
+ reject(
1698
+ result.errors.forEach((error) => {
1699
+ throw new SchemaValidationError(
1700
+ error.message,
1701
+ [error.context?.suggestion || error.code],
1702
+ result.warnings
1703
+ );
1704
+ })
1705
+ );
1706
+ } else {
1707
+ resolve(result.data!);
1708
+ }
1709
+ } catch (error) {
1710
+ reject(error);
1711
+ }
1712
+ }, 0);
1713
+ } catch (error) {
1714
+ reject(error);
1715
+ }
1716
+ });
1717
+ }
1718
+
1719
+ /**
1720
+ * Async safe parse - returns a promise with validation result object
1721
+ */
1722
+ async safeParseAsync(data: T): Promise<SchemaValidationResult<T>> {
1723
+ return new Promise((resolve) => {
1724
+ // Use setTimeout to make it truly async
1725
+ setTimeout(() => {
1726
+ try {
1727
+ const result = this.validate(data);
1728
+ resolve(result);
1729
+ } catch (error) {
1730
+ resolve({
1731
+ success: false,
1732
+ errors: [
1733
+ ErrorHandler.createSimpleError(
1734
+ `Unexpected validation error: ${error}`
1735
+ ),
1736
+ ],
1737
+ warnings: [],
1738
+ data: undefined,
1739
+ });
1740
+ }
1741
+ }, 0);
1742
+ });
1743
+ }
1744
+
1745
+ /**
1746
+ * Async safe parse with unknown data
1747
+ */
1748
+ async safeParseUnknownAsync(
1749
+ data: unknown
1750
+ ): Promise<SchemaValidationResult<T>> {
1751
+ return new Promise((resolve) => {
1752
+ setTimeout(() => {
1753
+ try {
1754
+ const result = this.validate(data);
1755
+ resolve(result);
1756
+ } catch (error) {
1757
+ resolve({
1758
+ success: false,
1759
+ errors: [
1760
+ ErrorHandler.createSimpleError(
1761
+ `Unexpected validation error: ${error}`
1762
+ ),
1763
+ ],
1764
+ warnings: [],
1765
+ data: undefined,
1766
+ });
1767
+ }
1768
+ }, 0);
1769
+ });
1770
+ }
1771
+
1772
+ /**
1773
+ * Enable strict mode (no unknown properties allowed)
1774
+ */
1775
+ strict(): InterfaceSchema<T> {
1776
+ return this.withOptions({ strict: true });
1777
+ }
1778
+
1779
+ /**
1780
+ * Enable loose mode (allow type coercion)
1781
+ */
1782
+ loose(): InterfaceSchema<T> {
1783
+ return this.withOptions({ loose: true });
1784
+ }
1785
+
1786
+ /**
1787
+ * Allow unknown properties (not strict about extra fields)
1788
+ * Returns a schema that accepts extra properties beyond the defined interface
1789
+ */
1790
+ allowUnknown(): InterfaceSchema<AllowUnknownSchema<T>> {
1791
+ return this.withOptions({ allowUnknown: true }) as InterfaceSchema<
1792
+ AllowUnknownSchema<T>
1793
+ >;
1794
+ }
1795
+
1796
+ /**
1797
+ * Set minimum constraints
1798
+ */
1799
+ min(value: number): InterfaceSchema<T> {
1800
+ return this.withOptions({
1801
+ min: value,
1802
+ minLength: value,
1803
+ minItems: value,
1804
+ });
1805
+ }
1806
+
1807
+ /**
1808
+ * Set maximum constraints
1809
+ */
1810
+ max(value: number): InterfaceSchema<T> {
1811
+ return this.withOptions({
1812
+ max: value,
1813
+ maxLength: value,
1814
+ maxItems: value,
1815
+ });
1816
+ }
1817
+
1818
+ /**
1819
+ * Require unique array values
1820
+ */
1821
+ unique(): InterfaceSchema<T> {
1822
+ return this.withOptions({ unique: true });
1823
+ }
1824
+
1825
+ /**
1826
+ * Set pattern for string validation
1827
+ */
1828
+ pattern(regex: RegExp): InterfaceSchema<T> {
1829
+ return this.withOptions({ pattern: regex });
1830
+ }
1831
+
1832
+ /**
1833
+ * Set default value
1834
+ */
1835
+ default(value: any): InterfaceSchema<T> {
1836
+ return this.withOptions({ default: value });
1837
+ }
1838
+ }