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.
- package/LICENSE +21 -0
- package/README.md +1305 -0
- package/dist/cjs/constants/SECURITY_CONSTANTS.js +49 -0
- package/dist/cjs/constants/SECURITY_CONSTANTS.js.map +1 -0
- package/dist/cjs/constants/VALIDATION_CONSTANTS.js +103 -0
- package/dist/cjs/constants/VALIDATION_CONSTANTS.js.map +1 -0
- package/dist/cjs/core/schema/extensions/SmartInference.js +200 -0
- package/dist/cjs/core/schema/extensions/SmartInference.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/Docs.js +100 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/Docs.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js +192 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js +174 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js +54 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js +50 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/index.js +15 -0
- package/dist/cjs/core/schema/extensions/components/AutoDocumentation/index.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js +70 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js +40 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js +19 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js +20 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js +49 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/index.js +98 -0
- package/dist/cjs/core/schema/extensions/components/ConditionalValidation/index.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/FormValidator.js +85 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/FormValidator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/LiveValidator.js +133 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/LiveValidator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/StreamValidator.js +351 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/StreamValidator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/index.js +109 -0
- package/dist/cjs/core/schema/extensions/components/RealtimeValidation/index.js.map +1 -0
- package/dist/cjs/core/schema/extensions/index.js +61 -0
- package/dist/cjs/core/schema/extensions/index.js.map +1 -0
- package/dist/cjs/core/schema/extensions/mods/index.js +51 -0
- package/dist/cjs/core/schema/extensions/mods/index.js.map +1 -0
- package/dist/cjs/core/schema/extensions/mods/openapi-converter.js +227 -0
- package/dist/cjs/core/schema/extensions/mods/openapi-converter.js.map +1 -0
- package/dist/cjs/core/schema/extensions/mods/typescript-generator.js +287 -0
- package/dist/cjs/core/schema/extensions/mods/typescript-generator.js.map +1 -0
- package/dist/cjs/core/schema/extensions/mods/validation-engine.js +224 -0
- package/dist/cjs/core/schema/extensions/mods/validation-engine.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/Interface.js +277 -0
- package/dist/cjs/core/schema/mode/interfaces/Interface.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js +1431 -0
- package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js +520 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js +624 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js +811 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js +599 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js +89 -0
- package/dist/cjs/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/errors/ErrorHandler.js +356 -0
- package/dist/cjs/core/schema/mode/interfaces/errors/ErrorHandler.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/errors/types/errors.type.js +80 -0
- package/dist/cjs/core/schema/mode/interfaces/errors/types/errors.type.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +778 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +523 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/ConditionalTypes.js +681 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/ConditionalTypes.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/IDESupport.js +430 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/IDESupport.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js +225 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/index.js +44 -0
- package/dist/cjs/core/schema/mode/interfaces/typescript/index.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js +1134 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js +256 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/TypeValidators.js +429 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/TypeValidators.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/UnionCache.js +404 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/UnionCache.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/ValidationHelpers.js +851 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/ValidationHelpers.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/passValidator.js +262 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/passValidator.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js +887 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/urlValidation.js +191 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/urlValidation.js.map +1 -0
- package/dist/cjs/core/schema/optimization/ObjectValidationCache.js +462 -0
- package/dist/cjs/core/schema/optimization/ObjectValidationCache.js.map +1 -0
- package/dist/cjs/core/schema/optimization/PerformanceMonitor.js +773 -0
- package/dist/cjs/core/schema/optimization/PerformanceMonitor.js.map +1 -0
- package/dist/cjs/core/schema/optimization/SchemaCompiler.js +600 -0
- package/dist/cjs/core/schema/optimization/SchemaCompiler.js.map +1 -0
- package/dist/cjs/core/types/ValidatorTypes.js +70 -0
- package/dist/cjs/core/types/ValidatorTypes.js.map +1 -0
- package/dist/cjs/core/types/parser.type.js +12 -0
- package/dist/cjs/core/types/parser.type.js.map +1 -0
- package/dist/cjs/core/utils/Make.js +61 -0
- package/dist/cjs/core/utils/Make.js.map +1 -0
- package/dist/cjs/core/utils/Mod.js +1033 -0
- package/dist/cjs/core/utils/Mod.js.map +1 -0
- package/dist/cjs/core/utils/UrlArgs.js +102 -0
- package/dist/cjs/core/utils/UrlArgs.js.map +1 -0
- package/dist/cjs/core/utils/arrayToEnum.js +18 -0
- package/dist/cjs/core/utils/arrayToEnum.js.map +1 -0
- package/dist/cjs/core/utils/createUrlArgsEnumFArray.js +13 -0
- package/dist/cjs/core/utils/createUrlArgsEnumFArray.js.map +1 -0
- package/dist/cjs/core/utils/securityHelpers.js +215 -0
- package/dist/cjs/core/utils/securityHelpers.js.map +1 -0
- package/dist/cjs/core/utils/securityValidatorHelpers.js +65 -0
- package/dist/cjs/core/utils/securityValidatorHelpers.js.map +1 -0
- package/dist/cjs/index.js +31 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/esm/constants/SECURITY_CONSTANTS.js +47 -0
- package/dist/esm/constants/SECURITY_CONSTANTS.js.map +1 -0
- package/dist/esm/constants/VALIDATION_CONSTANTS.js +98 -0
- package/dist/esm/constants/VALIDATION_CONSTANTS.js.map +1 -0
- package/dist/esm/core/schema/extensions/SmartInference.js +197 -0
- package/dist/esm/core/schema/extensions/SmartInference.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/Docs.js +98 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/Docs.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js +190 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js +172 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js +52 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js +48 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/index.js +12 -0
- package/dist/esm/core/schema/extensions/components/AutoDocumentation/index.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js +68 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js +38 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalElse.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js +17 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/ConditionalThen.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js +18 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js +45 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/index.js +92 -0
- package/dist/esm/core/schema/extensions/components/ConditionalValidation/index.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/FormValidator.js +83 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/FormValidator.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/LiveValidator.js +131 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/LiveValidator.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/StreamValidator.js +349 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/StreamValidator.js.map +1 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/index.js +103 -0
- package/dist/esm/core/schema/extensions/components/RealtimeValidation/index.js.map +1 -0
- package/dist/esm/core/schema/extensions/index.js +53 -0
- package/dist/esm/core/schema/extensions/index.js.map +1 -0
- package/dist/esm/core/schema/extensions/mods/index.js +47 -0
- package/dist/esm/core/schema/extensions/mods/index.js.map +1 -0
- package/dist/esm/core/schema/extensions/mods/openapi-converter.js +225 -0
- package/dist/esm/core/schema/extensions/mods/openapi-converter.js.map +1 -0
- package/dist/esm/core/schema/extensions/mods/typescript-generator.js +284 -0
- package/dist/esm/core/schema/extensions/mods/typescript-generator.js.map +1 -0
- package/dist/esm/core/schema/extensions/mods/validation-engine.js +222 -0
- package/dist/esm/core/schema/extensions/mods/validation-engine.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/Interface.js +269 -0
- package/dist/esm/core/schema/mode/interfaces/Interface.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js +1429 -0
- package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js +518 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js +620 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalAST.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js +809 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js +597 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/parser/ConditionalParser.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js +89 -0
- package/dist/esm/core/schema/mode/interfaces/conditional/types/ConditionalTypes.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/errors/ErrorHandler.js +354 -0
- package/dist/esm/core/schema/mode/interfaces/errors/ErrorHandler.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/errors/types/errors.type.js +80 -0
- package/dist/esm/core/schema/mode/interfaces/errors/types/errors.type.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +776 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +521 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/ConditionalTypes.js +681 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/ConditionalTypes.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/IDESupport.js +428 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/IDESupport.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js +223 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/index.js +35 -0
- package/dist/esm/core/schema/mode/interfaces/typescript/index.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js +1132 -0
- package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js +254 -0
- package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/TypeValidators.js +427 -0
- package/dist/esm/core/schema/mode/interfaces/validators/TypeValidators.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/UnionCache.js +400 -0
- package/dist/esm/core/schema/mode/interfaces/validators/UnionCache.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/ValidationHelpers.js +849 -0
- package/dist/esm/core/schema/mode/interfaces/validators/ValidationHelpers.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/mods/passValidator.js +260 -0
- package/dist/esm/core/schema/mode/interfaces/validators/mods/passValidator.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js +881 -0
- package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/validators/mods/urlValidation.js +189 -0
- package/dist/esm/core/schema/mode/interfaces/validators/mods/urlValidation.js.map +1 -0
- package/dist/esm/core/schema/optimization/ObjectValidationCache.js +460 -0
- package/dist/esm/core/schema/optimization/ObjectValidationCache.js.map +1 -0
- package/dist/esm/core/schema/optimization/PerformanceMonitor.js +771 -0
- package/dist/esm/core/schema/optimization/PerformanceMonitor.js.map +1 -0
- package/dist/esm/core/schema/optimization/SchemaCompiler.js +598 -0
- package/dist/esm/core/schema/optimization/SchemaCompiler.js.map +1 -0
- package/dist/esm/core/types/ValidatorTypes.js +65 -0
- package/dist/esm/core/types/ValidatorTypes.js.map +1 -0
- package/dist/esm/core/types/parser.type.js +12 -0
- package/dist/esm/core/types/parser.type.js.map +1 -0
- package/dist/esm/core/utils/Make.js +59 -0
- package/dist/esm/core/utils/Make.js.map +1 -0
- package/dist/esm/core/utils/Mod.js +1031 -0
- package/dist/esm/core/utils/Mod.js.map +1 -0
- package/dist/esm/core/utils/UrlArgs.js +98 -0
- package/dist/esm/core/utils/UrlArgs.js.map +1 -0
- package/dist/esm/core/utils/arrayToEnum.js +16 -0
- package/dist/esm/core/utils/arrayToEnum.js.map +1 -0
- package/dist/esm/core/utils/createUrlArgsEnumFArray.js +11 -0
- package/dist/esm/core/utils/createUrlArgsEnumFArray.js.map +1 -0
- package/dist/esm/core/utils/securityHelpers.js +207 -0
- package/dist/esm/core/utils/securityHelpers.js.map +1 -0
- package/dist/esm/core/utils/securityValidatorHelpers.js +62 -0
- package/dist/esm/core/utils/securityValidatorHelpers.js.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/schema.d.ts +2595 -0
- package/docs/ALL_TYPES.md +120 -0
- package/docs/API-STABILITY.md +336 -0
- package/docs/CONDITIONAL-VALIDATION.md +637 -0
- package/docs/EXAMPLES.md +876 -0
- package/docs/FIELD-TYPES.md +829 -0
- package/docs/GETTING-STARTED.md +394 -0
- package/docs/LIVE-UTILITY.md +1137 -0
- package/docs/QUICK-REFERENCE.md +346 -0
- package/docs/README.md +205 -0
- package/docs/VSCODE-EXTENSION.md +458 -0
- package/package.json +219 -0
- package/src/bench/BENCHMARK-RESULTS.md +211 -0
- package/src/bench/benchmark-results.json +148 -0
- package/src/bench/performance-comparison.ts +218 -0
- package/src/bench/precompilation-benchmark.ts +218 -0
- package/src/constants/SECURITY_CONSTANTS.ts +44 -0
- package/src/constants/VALIDATION_CONSTANTS.ts +176 -0
- package/src/core/README.md +395 -0
- package/src/core/compiler/SchemaTransformer.ts +279 -0
- package/src/core/compiler/TypeAnalyzer.ts +378 -0
- package/src/core/compiler/TypeScriptCompilerIntegration.ts +220 -0
- package/src/core/compiler/TypeToSchemaConverter.ts +288 -0
- package/src/core/index.ts +70 -0
- package/src/core/schema/extensions/AutoDocumentation.ts +572 -0
- package/src/core/schema/extensions/ConditionalValidation.ts +330 -0
- package/src/core/schema/extensions/README.md +171 -0
- package/src/core/schema/extensions/RealtimeValidation.ts +656 -0
- package/src/core/schema/extensions/SmartInference.ts +224 -0
- package/src/core/schema/extensions/components/AutoDocumentation/Docs.ts +98 -0
- package/src/core/schema/extensions/components/AutoDocumentation/DocumentationGenerator.ts +201 -0
- package/src/core/schema/extensions/components/AutoDocumentation/InteractiveDocumentationGenerator.ts +176 -0
- package/src/core/schema/extensions/components/AutoDocumentation/OpenAPIGenerator.ts +175 -0
- package/src/core/schema/extensions/components/AutoDocumentation/SchemaAnalyzer.ts +49 -0
- package/src/core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.ts +54 -0
- package/src/core/schema/extensions/components/AutoDocumentation/index.ts +17 -0
- package/src/core/schema/extensions/components/ConditionalValidation/ConditionalBuilder.ts +101 -0
- package/src/core/schema/extensions/components/ConditionalValidation/ConditionalElse.ts +65 -0
- package/src/core/schema/extensions/components/ConditionalValidation/ConditionalThen.ts +33 -0
- package/src/core/schema/extensions/components/ConditionalValidation/Extend.ts +75 -0
- package/src/core/schema/extensions/components/ConditionalValidation/MultiConditionalBuilder.ts +16 -0
- package/src/core/schema/extensions/components/ConditionalValidation/MultiConditionalThen.ts +50 -0
- package/src/core/schema/extensions/components/ConditionalValidation/index.ts +104 -0
- package/src/core/schema/extensions/components/RealtimeValidation/FormValidator.ts +88 -0
- package/src/core/schema/extensions/components/RealtimeValidation/LiveValidator.ts +171 -0
- package/src/core/schema/extensions/components/RealtimeValidation/StreamValidator.ts +397 -0
- package/src/core/schema/extensions/components/RealtimeValidation/index.ts +114 -0
- package/src/core/schema/extensions/index.ts +76 -0
- package/src/core/schema/extensions/mods/index.ts +131 -0
- package/src/core/schema/extensions/mods/openapi-converter.ts +338 -0
- package/src/core/schema/extensions/mods/typescript-generator.ts +379 -0
- package/src/core/schema/extensions/mods/validation-engine.ts +295 -0
- package/src/core/schema/mode/interfaces/Interface.ts +364 -0
- package/src/core/schema/mode/interfaces/InterfaceSchema.ts +1838 -0
- package/src/core/schema/mode/interfaces/README.md +278 -0
- package/src/core/schema/mode/interfaces/conditional/evaluator/ConditionalEvaluator.ts +657 -0
- package/src/core/schema/mode/interfaces/conditional/parser/ConditionalAST.ts +826 -0
- package/src/core/schema/mode/interfaces/conditional/parser/ConditionalLexer.ts +992 -0
- package/src/core/schema/mode/interfaces/conditional/parser/ConditionalParser.ts +803 -0
- package/src/core/schema/mode/interfaces/conditional/parser/readme.md +406 -0
- package/src/core/schema/mode/interfaces/conditional/types/ConditionalTypes.ts +273 -0
- package/src/core/schema/mode/interfaces/errors/ErrorHandler.ts +624 -0
- package/src/core/schema/mode/interfaces/errors/types/errors.type.ts +102 -0
- package/src/core/schema/mode/interfaces/precompilation/FieldPrecompilers.ts +962 -0
- package/src/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.ts +667 -0
- package/src/core/schema/mode/interfaces/typescript/ConditionalTypes.ts +1534 -0
- package/src/core/schema/mode/interfaces/typescript/IDESupport.ts +534 -0
- package/src/core/schema/mode/interfaces/typescript/TypeInference.ts +737 -0
- package/src/core/schema/mode/interfaces/typescript/index.ts +92 -0
- package/src/core/schema/mode/interfaces/validators/ConstraintParser.ts +1438 -0
- package/src/core/schema/mode/interfaces/validators/EnhancedErrorReporting.ts +227 -0
- package/src/core/schema/mode/interfaces/validators/TypeGuards.ts +288 -0
- package/src/core/schema/mode/interfaces/validators/TypeValidators.ts +660 -0
- package/src/core/schema/mode/interfaces/validators/UnionCache.ts +508 -0
- package/src/core/schema/mode/interfaces/validators/ValidationHelpers.ts +1257 -0
- package/src/core/schema/mode/interfaces/validators/index.ts +21 -0
- package/src/core/schema/mode/interfaces/validators/mods/passValidator.ts +424 -0
- package/src/core/schema/mode/interfaces/validators/mods/securityValidator.ts +1634 -0
- package/src/core/schema/mode/interfaces/validators/mods/urlValidation.ts +333 -0
- package/src/core/schema/optimization/ObjectValidationCache.ts +560 -0
- package/src/core/schema/optimization/PerformanceInitializer.ts +188 -0
- package/src/core/schema/optimization/PerformanceMonitor.ts +898 -0
- package/src/core/schema/optimization/SchemaCompiler.ts +730 -0
- package/src/core/testing/TestDataGenerator.ts +590 -0
- package/src/core/types/SchemaValidator.type.ts +210 -0
- package/src/core/types/ValidatorTypes.ts +93 -0
- package/src/core/types/extension.type.ts +109 -0
- package/src/core/types/objValidationCache.ts +17 -0
- package/src/core/types/parser.type.ts +15 -0
- package/src/core/types/perfoMonitor.ts +37 -0
- package/src/core/types/scompiler.ts +22 -0
- package/src/core/types/securityValidator.type.ts +10 -0
- package/src/core/types/types.ts +154 -0
- package/src/core/utils/Make.ts +97 -0
- package/src/core/utils/Mod.ts +1168 -0
- package/src/core/utils/UrlArgs.ts +124 -0
- package/src/core/utils/arrayToEnum.ts +89 -0
- package/src/core/utils/createUrlArgsEnumFArray.ts +11 -0
- package/src/core/utils/securityHelpers.ts +341 -0
- package/src/core/utils/securityValidatorHelpers.ts +76 -0
- package/src/index.ts +124 -0
|
@@ -0,0 +1,1438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constraint Parser Module - Enhanced Robust Version
|
|
3
|
+
*
|
|
4
|
+
* Optimized parsing of constraint syntax like "string(3,20)", "number(0,100)?", etc.
|
|
5
|
+
* Uses caching, pre-compiled patterns, and robust regex validation for maximum reliability.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
ParsedConstraints,
|
|
10
|
+
ConstraintType,
|
|
11
|
+
} from "../../../../types/parser.type";
|
|
12
|
+
import {
|
|
13
|
+
SUPPORTED_VALIDATOR_TYPES,
|
|
14
|
+
VALID_CONDITIONNAL_TYPES,
|
|
15
|
+
} from "../../../../types/ValidatorTypes";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Enhanced constraint parser with robust regex patterns and bulletproof validation
|
|
19
|
+
*/
|
|
20
|
+
export class ConstraintParser {
|
|
21
|
+
// Private static properties for better encapsulation
|
|
22
|
+
private static readonly _parseCache = new Map<string, ParsedConstraints>();
|
|
23
|
+
private static readonly _maxCacheSize = 1000;
|
|
24
|
+
private static _cacheHits = 0;
|
|
25
|
+
private static _cacheMisses = 0;
|
|
26
|
+
|
|
27
|
+
// pre-compiled regex patterns with stronger validation
|
|
28
|
+
private static readonly _patterns = {
|
|
29
|
+
// Robust constraint pattern - handles complex nested patterns
|
|
30
|
+
constraint: /^([a-zA-Z_][a-zA-Z0-9_]*(?:\[\])*)\((.+)\)$/,
|
|
31
|
+
|
|
32
|
+
// Enhanced regex pattern detection with proper escaping
|
|
33
|
+
regex: /^\/(.+?)\/([gimsuvy]*)$/,
|
|
34
|
+
|
|
35
|
+
// Precise comma splitting that handles whitespace
|
|
36
|
+
commaSplit: /\s*,\s*/,
|
|
37
|
+
|
|
38
|
+
// Robust numeric validation including scientific notation and edge cases
|
|
39
|
+
numeric: /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/,
|
|
40
|
+
|
|
41
|
+
// Strict base type validation
|
|
42
|
+
baseType: /^[a-zA-Z_][a-zA-Z0-9_]*(?:\[\])*$/,
|
|
43
|
+
|
|
44
|
+
// Enhanced complex constraint detection
|
|
45
|
+
complexConstraint: /^[a-zA-Z_][a-zA-Z0-9_]*(?:\[\])*\([^)]*\)$/,
|
|
46
|
+
|
|
47
|
+
// Union type detection with balanced parentheses
|
|
48
|
+
unionType: /^\([^()]*(?:\|[^()]*)+\)$/,
|
|
49
|
+
|
|
50
|
+
// Record type detection (both cases)
|
|
51
|
+
recordTypeLower: /^record<[^<>]+>$/i,
|
|
52
|
+
recordTypeUpper: /^Record<[^<>]+>$/,
|
|
53
|
+
|
|
54
|
+
// Optional marker validation
|
|
55
|
+
optionalMarker: /\?$/,
|
|
56
|
+
|
|
57
|
+
// Required marker validation
|
|
58
|
+
requiredMarker: /!$/,
|
|
59
|
+
|
|
60
|
+
// Whitespace validation
|
|
61
|
+
whitespaceOnly: /^\s*$/,
|
|
62
|
+
|
|
63
|
+
// Constraint key validation
|
|
64
|
+
constraintKey: /^[a-zA-Z][a-zA-Z0-9_]*$/,
|
|
65
|
+
|
|
66
|
+
// Balanced parentheses validation
|
|
67
|
+
balancedParens: /^[^()]*(?:\([^()]*\)[^()]*)*$/,
|
|
68
|
+
|
|
69
|
+
// Array type detection
|
|
70
|
+
arrayType: /^[a-zA-Z_][a-zA-Z0-9_]*\[\]$/,
|
|
71
|
+
|
|
72
|
+
// Equal sign prefix for literal values
|
|
73
|
+
literalValue: /^=/,
|
|
74
|
+
|
|
75
|
+
// Boolean value validation
|
|
76
|
+
booleanValue: /^(?:true|false)$/i,
|
|
77
|
+
|
|
78
|
+
// Enhanced semicolon split for complex constraints
|
|
79
|
+
semicolonSplit: /\s*;\s*/,
|
|
80
|
+
|
|
81
|
+
// Colon split for key-value pairs
|
|
82
|
+
colonSplit: /\s*:\s*/,
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
85
|
+
// Character codes for optimized checks
|
|
86
|
+
private static readonly _charCodes = {
|
|
87
|
+
questionMark: 63, // '?'
|
|
88
|
+
exclamation: 33, // '!'
|
|
89
|
+
openParen: 40, // '('
|
|
90
|
+
closeParen: 41, // ')'
|
|
91
|
+
comma: 44, // ','
|
|
92
|
+
semicolon: 59, // ';'
|
|
93
|
+
colon: 58, // ':'
|
|
94
|
+
pipe: 124, // '|'
|
|
95
|
+
openBracket: 91, // '['
|
|
96
|
+
closeBracket: 93, // ']'
|
|
97
|
+
slash: 47, // '/'
|
|
98
|
+
backslash: 92, // '\'
|
|
99
|
+
equal: 61, // '='
|
|
100
|
+
} as const;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Parse constraint syntax with aggressive caching and robust validation
|
|
104
|
+
*/
|
|
105
|
+
static parseConstraints(fieldType: string): ParsedConstraints {
|
|
106
|
+
if (!this._isValidInput(fieldType)) {
|
|
107
|
+
throw new Error("Invalid field type: must be a non-empty string");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Check cache first
|
|
111
|
+
const cached = this._parseCache.get(fieldType);
|
|
112
|
+
if (cached) {
|
|
113
|
+
this._cacheHits++;
|
|
114
|
+
return this._deepClone(cached);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this._cacheMisses++;
|
|
118
|
+
const result = this._parseConstraintsInternal(fieldType);
|
|
119
|
+
|
|
120
|
+
// Cache the result with size limit
|
|
121
|
+
this._addToCache(fieldType, result);
|
|
122
|
+
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Enhanced input validation
|
|
128
|
+
*/
|
|
129
|
+
private static _isValidInput(input: unknown): input is string {
|
|
130
|
+
return (
|
|
131
|
+
typeof input === "string" &&
|
|
132
|
+
input.length > 0 &&
|
|
133
|
+
!this._patterns.whitespaceOnly.test(input)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Deep clone utility for cache results
|
|
139
|
+
*/
|
|
140
|
+
private static _deepClone(obj: ParsedConstraints): ParsedConstraints {
|
|
141
|
+
const cloned: ParsedConstraints = {
|
|
142
|
+
type: obj.type,
|
|
143
|
+
constraints: {},
|
|
144
|
+
optional: obj.optional,
|
|
145
|
+
required: obj.required,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// Deep clone constraints object
|
|
149
|
+
if (obj.constraints && typeof obj.constraints === "object") {
|
|
150
|
+
for (const [key, value] of Object.entries(obj.constraints)) {
|
|
151
|
+
if (value instanceof RegExp) {
|
|
152
|
+
cloned.constraints[key] = new RegExp(value.source, value.flags);
|
|
153
|
+
} else if (typeof value === "object" && value !== null) {
|
|
154
|
+
cloned.constraints[key] = { ...value };
|
|
155
|
+
} else {
|
|
156
|
+
cloned.constraints[key] = value;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return cloned;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Enhanced internal parsing logic with robust error handling
|
|
166
|
+
*/
|
|
167
|
+
private static _parseConstraintsInternal(
|
|
168
|
+
fieldType: string
|
|
169
|
+
): ParsedConstraints {
|
|
170
|
+
let optional = false;
|
|
171
|
+
let required = false;
|
|
172
|
+
let type = this._sanitizeInput(fieldType);
|
|
173
|
+
let constraints: any = {};
|
|
174
|
+
|
|
175
|
+
if (!type) {
|
|
176
|
+
throw new Error("Field type cannot be empty after sanitization");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Enhanced optional marker detection
|
|
180
|
+
if (this._hasOptionalMarker(type)) {
|
|
181
|
+
optional = true;
|
|
182
|
+
type = this._removeOptionalMarker(type);
|
|
183
|
+
|
|
184
|
+
if (!type) {
|
|
185
|
+
throw new Error('Invalid field type: cannot be only "?"');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Enhanced required marker detection
|
|
190
|
+
if (this._hasRequiredMarker(type)) {
|
|
191
|
+
required = true;
|
|
192
|
+
type = this._removeRequiredMarker(type);
|
|
193
|
+
|
|
194
|
+
if (!type) {
|
|
195
|
+
throw new Error('Invalid field type: cannot be only "!"');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Enhanced union type detection
|
|
200
|
+
if (this._isUnionTypeInParentheses(type)) {
|
|
201
|
+
return { type, constraints: {}, optional, required };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Enhanced constraint parsing with robust validation
|
|
205
|
+
const constraintMatch = this._parseBalancedConstraints(type);
|
|
206
|
+
if (constraintMatch) {
|
|
207
|
+
const { baseType, constraintStr } = constraintMatch;
|
|
208
|
+
type = baseType;
|
|
209
|
+
|
|
210
|
+
if (constraintStr) {
|
|
211
|
+
try {
|
|
212
|
+
constraints = this._parseConstraintString(constraintStr, baseType);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`Invalid constraint syntax in "${fieldType}": ${this._getErrorMessage(error)}`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Check for conditional expressions (when ... *? ... : ...)
|
|
222
|
+
if (this._isConditionalExpression(type)) {
|
|
223
|
+
return { type, constraints: {}, optional, required };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Enhanced base type validation
|
|
227
|
+
if (!this._isValidBaseType(type)) {
|
|
228
|
+
throw new Error(`Invalid base type: "${type}"`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return { type, constraints, optional, required };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Check if type is a conditional expression using secure regex pattern
|
|
236
|
+
*/
|
|
237
|
+
private static _isConditionalExpression(type: string): boolean {
|
|
238
|
+
// Secure regex pattern to match: when <condition> *? <thenValue> [: <elseValue>]
|
|
239
|
+
const conditionalPattern = /^\s*when\s+.+?\s*\*\?\s*.+/;
|
|
240
|
+
return conditionalPattern.test(type);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Enhanced input sanitization
|
|
245
|
+
*/
|
|
246
|
+
private static _sanitizeInput(input: string): string {
|
|
247
|
+
if (typeof input !== "string") {
|
|
248
|
+
throw new Error("Input must be a string");
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Trim whitespace but preserve internal structure
|
|
252
|
+
return input.trim().replace(/\s+/g, " ");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Robust optional marker detection
|
|
257
|
+
*/
|
|
258
|
+
private static _hasOptionalMarker(type: string): boolean {
|
|
259
|
+
return (
|
|
260
|
+
type.length > 0 &&
|
|
261
|
+
type.charCodeAt(type.length - 1) === this._charCodes.questionMark &&
|
|
262
|
+
this._patterns.optionalMarker.test(type)
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Safe optional marker removal
|
|
268
|
+
*/
|
|
269
|
+
private static _removeOptionalMarker(type: string): string {
|
|
270
|
+
if (!this._hasOptionalMarker(type)) {
|
|
271
|
+
return type;
|
|
272
|
+
}
|
|
273
|
+
return type.slice(0, -1).trim();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Robust required marker detection
|
|
278
|
+
*/
|
|
279
|
+
private static _hasRequiredMarker(type: string): boolean {
|
|
280
|
+
return (
|
|
281
|
+
type.length > 0 &&
|
|
282
|
+
type.charCodeAt(type.length - 1) === this._charCodes.exclamation &&
|
|
283
|
+
this._patterns.requiredMarker.test(type)
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Safe required marker removal
|
|
289
|
+
*/
|
|
290
|
+
private static _removeRequiredMarker(type: string): string {
|
|
291
|
+
if (!this._hasRequiredMarker(type)) {
|
|
292
|
+
return type;
|
|
293
|
+
}
|
|
294
|
+
return type.slice(0, -1).trim();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Enhanced union type detection with regex validation
|
|
299
|
+
*/
|
|
300
|
+
private static _isUnionTypeInParentheses(type: string): boolean {
|
|
301
|
+
return (
|
|
302
|
+
this._patterns.unionType.test(type) &&
|
|
303
|
+
this._containsPipeOperator(type) &&
|
|
304
|
+
this._hasBalancedParentheses(type)
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Check for pipe operator in union types
|
|
310
|
+
*/
|
|
311
|
+
private static _containsPipeOperator(type: string): boolean {
|
|
312
|
+
for (let i = 0; i < type.length; i++) {
|
|
313
|
+
if (type.charCodeAt(i) === this._charCodes.pipe) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Validate balanced parentheses
|
|
322
|
+
*/
|
|
323
|
+
private static _hasBalancedParentheses(input: string): boolean {
|
|
324
|
+
let depth = 0;
|
|
325
|
+
|
|
326
|
+
for (let i = 0; i < input.length; i++) {
|
|
327
|
+
const charCode = input.charCodeAt(i);
|
|
328
|
+
|
|
329
|
+
if (charCode === this._charCodes.openParen) {
|
|
330
|
+
depth++;
|
|
331
|
+
} else if (charCode === this._charCodes.closeParen) {
|
|
332
|
+
depth--;
|
|
333
|
+
if (depth < 0) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return depth === 0;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Enhanced constraint parsing with robust parentheses handling
|
|
344
|
+
*/
|
|
345
|
+
private static _parseBalancedConstraints(
|
|
346
|
+
type: string
|
|
347
|
+
): { baseType: string; constraintStr: string } | null {
|
|
348
|
+
const match = type.match(this._patterns.constraint);
|
|
349
|
+
if (!match) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const [, baseType, constraintStr] = match;
|
|
354
|
+
|
|
355
|
+
// Enhanced base type validation
|
|
356
|
+
if (!this._patterns.baseType.test(baseType)) {
|
|
357
|
+
throw new Error(`Invalid base type format: "${baseType}"`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Validate constraint string is not empty
|
|
361
|
+
if (!constraintStr || this._patterns.whitespaceOnly.test(constraintStr)) {
|
|
362
|
+
throw new Error(`Empty constraint string in: "${type}"`);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Validate balanced parentheses in constraint string
|
|
366
|
+
if (!this._validateConstraintParentheses(constraintStr)) {
|
|
367
|
+
throw new Error(`Unbalanced parentheses in constraint: "${type}"`);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return { baseType, constraintStr };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Validate parentheses balance in constraint strings
|
|
375
|
+
*/
|
|
376
|
+
private static _validateConstraintParentheses(
|
|
377
|
+
constraintStr: string
|
|
378
|
+
): boolean {
|
|
379
|
+
let depth = 0;
|
|
380
|
+
let inRegex = false;
|
|
381
|
+
let escaped = false;
|
|
382
|
+
|
|
383
|
+
for (let i = 0; i < constraintStr.length; i++) {
|
|
384
|
+
const charCode = constraintStr.charCodeAt(i);
|
|
385
|
+
const char = constraintStr[i];
|
|
386
|
+
|
|
387
|
+
// Handle regex pattern detection
|
|
388
|
+
if (charCode === this._charCodes.slash && !escaped) {
|
|
389
|
+
inRegex = !inRegex;
|
|
390
|
+
escaped = false;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Handle escaping
|
|
395
|
+
if (charCode === this._charCodes.backslash && !escaped) {
|
|
396
|
+
escaped = true;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Skip parentheses inside regex patterns
|
|
401
|
+
if (!inRegex) {
|
|
402
|
+
if (charCode === this._charCodes.openParen && !escaped) {
|
|
403
|
+
depth++;
|
|
404
|
+
} else if (charCode === this._charCodes.closeParen && !escaped) {
|
|
405
|
+
depth--;
|
|
406
|
+
if (depth < 0) {
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
escaped = false;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return depth === 0;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Enhanced constraint string parsing with robust error handling
|
|
420
|
+
*/
|
|
421
|
+
private static _parseConstraintString(
|
|
422
|
+
constraintStr: string,
|
|
423
|
+
baseType: string
|
|
424
|
+
): any {
|
|
425
|
+
const trimmed = constraintStr.trim();
|
|
426
|
+
if (!trimmed) {
|
|
427
|
+
return {};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const constraints: any = {};
|
|
431
|
+
|
|
432
|
+
// Enhanced regex pattern detection
|
|
433
|
+
const regexMatch = this._parseRegexPattern(trimmed);
|
|
434
|
+
if (regexMatch) {
|
|
435
|
+
constraints.pattern = regexMatch;
|
|
436
|
+
return constraints;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Enhanced semicolon-separated complex constraints
|
|
440
|
+
if (this._containsCharCode(trimmed, this._charCodes.semicolon)) {
|
|
441
|
+
return this._parseComplexConstraints(trimmed);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Enhanced min,max constraints
|
|
445
|
+
if (this._containsCharCode(trimmed, this._charCodes.comma)) {
|
|
446
|
+
return this._parseMinMaxConstraints(trimmed, baseType);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Enhanced single value constraint
|
|
450
|
+
if (this._isValidNumericValue(trimmed)) {
|
|
451
|
+
const val = this._parseNumericValue(trimmed);
|
|
452
|
+
this._setConstraintValue(constraints, baseType, ConstraintType.Max, val);
|
|
453
|
+
return constraints;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
throw new Error(`Unrecognized constraint format: "${trimmed}"`);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Enhanced regex pattern parsing
|
|
461
|
+
*/
|
|
462
|
+
private static _parseRegexPattern(input: string): RegExp | null {
|
|
463
|
+
const match = input.match(this._patterns.regex);
|
|
464
|
+
if (!match) {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
const [, pattern, flags] = match;
|
|
470
|
+
|
|
471
|
+
// Validate flags
|
|
472
|
+
if (flags && !this._isValidRegexFlags(flags)) {
|
|
473
|
+
throw new Error(`Invalid regex flags: "${flags}"`);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return new RegExp(pattern, flags || "");
|
|
477
|
+
} catch (error) {
|
|
478
|
+
throw new Error(`Invalid regex pattern: ${this._getErrorMessage(error)}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Validate regex flags
|
|
484
|
+
*/
|
|
485
|
+
private static _isValidRegexFlags(flags: string): boolean {
|
|
486
|
+
const validFlags = new Set(["g", "i", "m", "s", "u", "v", "y"]);
|
|
487
|
+
const flagSet = new Set();
|
|
488
|
+
|
|
489
|
+
for (const flag of flags) {
|
|
490
|
+
if (!validFlags.has(flag)) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
if (flagSet.has(flag)) {
|
|
494
|
+
return false; // Duplicate flag
|
|
495
|
+
}
|
|
496
|
+
flagSet.add(flag);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Check if string contains specific character code
|
|
504
|
+
*/
|
|
505
|
+
private static _containsCharCode(str: string, charCode: number): boolean {
|
|
506
|
+
for (let i = 0; i < str.length; i++) {
|
|
507
|
+
if (str.charCodeAt(i) === charCode) {
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Enhanced numeric value validation
|
|
516
|
+
*/
|
|
517
|
+
private static _isValidNumericValue(value: string): boolean {
|
|
518
|
+
if (!value || typeof value !== "string") {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return this._patterns.numeric.test(value.trim());
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Safe numeric value parsing
|
|
527
|
+
*/
|
|
528
|
+
private static _parseNumericValue(value: string): number {
|
|
529
|
+
const trimmed = value.trim();
|
|
530
|
+
|
|
531
|
+
if (!this._isValidNumericValue(trimmed)) {
|
|
532
|
+
throw new Error(`Invalid numeric value: "${value}"`);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const parsed = Number(trimmed);
|
|
536
|
+
|
|
537
|
+
if (!Number.isFinite(parsed)) {
|
|
538
|
+
throw new Error(`Non-finite numeric value: "${value}"`);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return parsed;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Enhanced min,max constraint parsing
|
|
546
|
+
*/
|
|
547
|
+
private static _parseMinMaxConstraints(
|
|
548
|
+
constraintStr: string,
|
|
549
|
+
baseType: string
|
|
550
|
+
): any {
|
|
551
|
+
const constraints: any = {};
|
|
552
|
+
const parts = constraintStr.split(this._patterns.commaSplit);
|
|
553
|
+
|
|
554
|
+
if (parts.length > 2) {
|
|
555
|
+
throw new Error(
|
|
556
|
+
`Too many constraint values. Expected format: "min,max" but got: "${constraintStr}"`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const [minStr, maxStr] = parts;
|
|
561
|
+
|
|
562
|
+
// Enhanced minimum value parsing
|
|
563
|
+
if (minStr && !this._patterns.whitespaceOnly.test(minStr)) {
|
|
564
|
+
const minVal = this._parseNumericValue(minStr);
|
|
565
|
+
this._setConstraintValue(
|
|
566
|
+
constraints,
|
|
567
|
+
baseType,
|
|
568
|
+
ConstraintType.Min,
|
|
569
|
+
minVal
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// Enhanced maximum value parsing
|
|
574
|
+
if (maxStr && !this._patterns.whitespaceOnly.test(maxStr)) {
|
|
575
|
+
const maxVal = this._parseNumericValue(maxStr);
|
|
576
|
+
this._setConstraintValue(
|
|
577
|
+
constraints,
|
|
578
|
+
baseType,
|
|
579
|
+
ConstraintType.Max,
|
|
580
|
+
maxVal
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// Enhanced min/max relationship validation
|
|
585
|
+
this._validateMinMaxRelationship(constraints);
|
|
586
|
+
|
|
587
|
+
return constraints;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Validate min/max constraint relationships
|
|
592
|
+
*/
|
|
593
|
+
private static _validateMinMaxRelationship(constraints: any): void {
|
|
594
|
+
const pairs = [
|
|
595
|
+
["min", "max"],
|
|
596
|
+
["minLength", "maxLength"],
|
|
597
|
+
["minItems", "maxItems"],
|
|
598
|
+
];
|
|
599
|
+
|
|
600
|
+
for (const [minKey, maxKey] of pairs) {
|
|
601
|
+
if (
|
|
602
|
+
constraints[minKey] !== undefined &&
|
|
603
|
+
constraints[maxKey] !== undefined
|
|
604
|
+
) {
|
|
605
|
+
if (constraints[minKey] > constraints[maxKey]) {
|
|
606
|
+
throw new Error(
|
|
607
|
+
`${minKey} value (${constraints[minKey]}) cannot be greater than ${maxKey} value (${constraints[maxKey]})`
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Enhanced constraint value setting with robust validation
|
|
616
|
+
*/
|
|
617
|
+
private static _setConstraintValue(
|
|
618
|
+
constraints: any,
|
|
619
|
+
baseType: string,
|
|
620
|
+
constraintType: ConstraintType.Min | ConstraintType.Max,
|
|
621
|
+
value: number
|
|
622
|
+
): void {
|
|
623
|
+
// Enhanced negative value validation
|
|
624
|
+
if (!Number.isFinite(value)) {
|
|
625
|
+
throw new Error(`Constraint value must be finite: ${value}`);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Type-specific negative value validation
|
|
629
|
+
if (this._isStringType(baseType) && value < 0) {
|
|
630
|
+
throw new Error("String length constraints cannot be negative");
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (this._isArrayType(baseType) && value < 0) {
|
|
634
|
+
throw new Error("Array length constraints cannot be negative");
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Set appropriate constraint based on type
|
|
638
|
+
if (this._isArrayType(baseType)) {
|
|
639
|
+
constraints[
|
|
640
|
+
constraintType === ConstraintType.Min
|
|
641
|
+
? ConstraintType.MinItems
|
|
642
|
+
: ConstraintType.MaxItems
|
|
643
|
+
] = value;
|
|
644
|
+
} else if (this._isStringType(baseType)) {
|
|
645
|
+
constraints[
|
|
646
|
+
constraintType === ConstraintType.Min
|
|
647
|
+
? ConstraintType.MinLength
|
|
648
|
+
: ConstraintType.MaxLength
|
|
649
|
+
] = value;
|
|
650
|
+
} else {
|
|
651
|
+
constraints[constraintType] = value;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Enhanced string type detection
|
|
657
|
+
*/
|
|
658
|
+
private static _isStringType(type: string): boolean {
|
|
659
|
+
return (
|
|
660
|
+
type === "string" ||
|
|
661
|
+
(this._patterns.baseType.test(type) && type.includes("string"))
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Enhanced array type detection
|
|
667
|
+
*/
|
|
668
|
+
private static _isArrayType(type: string): boolean {
|
|
669
|
+
return this._patterns.arrayType.test(type) || type.endsWith("[]");
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Enhanced base type validation with comprehensive checks
|
|
674
|
+
*/
|
|
675
|
+
private static _isValidBaseType(type: string): boolean {
|
|
676
|
+
if (!type || typeof type !== "string") {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Enhanced whitespace validation
|
|
681
|
+
if (this._patterns.whitespaceOnly.test(type)) {
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Check valid conditional types
|
|
686
|
+
if (VALID_CONDITIONNAL_TYPES.includes(type)) {
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Enhanced union type validation
|
|
691
|
+
if (this._containsPipeOperator(type)) {
|
|
692
|
+
return this._validateUnionType(type);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// Enhanced literal value validation
|
|
696
|
+
if (this._patterns.literalValue.test(type)) {
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// Enhanced Record type validation
|
|
701
|
+
if (this._isRecordType(type)) {
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Enhanced supported validator types check
|
|
706
|
+
if (SUPPORTED_VALIDATOR_TYPES.includes(type as any)) {
|
|
707
|
+
return true;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// Enhanced base type pattern validation
|
|
711
|
+
return this._patterns.baseType.test(type);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Validate union types
|
|
716
|
+
*/
|
|
717
|
+
private static _validateUnionType(type: string): boolean {
|
|
718
|
+
const parts = type.split("|");
|
|
719
|
+
|
|
720
|
+
if (parts.length < 2) {
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return parts.every((part) => {
|
|
725
|
+
const trimmed = part.trim();
|
|
726
|
+
return trimmed.length > 0 && !this._patterns.whitespaceOnly.test(trimmed);
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Enhanced Record type detection
|
|
732
|
+
*/
|
|
733
|
+
private static _isRecordType(type: string): boolean {
|
|
734
|
+
return (
|
|
735
|
+
this._patterns.recordTypeLower.test(type) ||
|
|
736
|
+
this._patterns.recordTypeUpper.test(type)
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Enhanced cache management with deep cloning
|
|
742
|
+
*/
|
|
743
|
+
private static _addToCache(key: string, value: ParsedConstraints): void {
|
|
744
|
+
if (this._parseCache.size >= this._maxCacheSize) {
|
|
745
|
+
const firstKey = this._parseCache.keys().next().value;
|
|
746
|
+
if (firstKey) {
|
|
747
|
+
this._parseCache.delete(firstKey);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
this._parseCache.set(key, this._deepClone(value));
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Enhanced complex constraint parsing
|
|
756
|
+
*/
|
|
757
|
+
private static _parseComplexConstraints(constraintStr: string): any {
|
|
758
|
+
const constraints: any = {};
|
|
759
|
+
const parts = constraintStr
|
|
760
|
+
.split(this._patterns.semicolonSplit)
|
|
761
|
+
.map((part) => part.trim())
|
|
762
|
+
.filter((part) => !this._patterns.whitespaceOnly.test(part));
|
|
763
|
+
|
|
764
|
+
if (parts.length === 0) {
|
|
765
|
+
throw new Error("Empty complex constraint string");
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
for (const part of parts) {
|
|
769
|
+
try {
|
|
770
|
+
this._parseComplexConstraintPart(constraints, part);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
throw new Error(
|
|
773
|
+
`Error parsing constraint "${part}": ${this._getErrorMessage(error)}`
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
return constraints;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Parse individual complex constraint part
|
|
783
|
+
*/
|
|
784
|
+
private static _parseComplexConstraintPart(
|
|
785
|
+
constraints: any,
|
|
786
|
+
part: string
|
|
787
|
+
): void {
|
|
788
|
+
const colonParts = part.split(this._patterns.colonSplit);
|
|
789
|
+
|
|
790
|
+
if (colonParts.length !== 2) {
|
|
791
|
+
throw new Error(
|
|
792
|
+
`Invalid constraint format. Expected "key:value" but got: "${part}"`
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
const [key, value] = colonParts;
|
|
797
|
+
|
|
798
|
+
if (
|
|
799
|
+
this._patterns.whitespaceOnly.test(key) ||
|
|
800
|
+
this._patterns.whitespaceOnly.test(value)
|
|
801
|
+
) {
|
|
802
|
+
throw new Error(
|
|
803
|
+
`Invalid constraint format. Both key and value must be non-empty: "${part}"`
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if (!this._patterns.constraintKey.test(key)) {
|
|
808
|
+
throw new Error(`Invalid constraint key format: "${key}"`);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
this._parseComplexConstraintPair(constraints, key, value);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Enhanced individual constraint key-value pair parsing
|
|
816
|
+
*/
|
|
817
|
+
private static _parseComplexConstraintPair(
|
|
818
|
+
constraints: any,
|
|
819
|
+
key: string,
|
|
820
|
+
value: string
|
|
821
|
+
): void {
|
|
822
|
+
switch (key) {
|
|
823
|
+
case ConstraintType.Min:
|
|
824
|
+
case ConstraintType.Max:
|
|
825
|
+
case ConstraintType.MinLength:
|
|
826
|
+
case ConstraintType.MaxLength:
|
|
827
|
+
case ConstraintType.MinItems:
|
|
828
|
+
case ConstraintType.MaxItems:
|
|
829
|
+
const numValue = this._parseNumericValue(value);
|
|
830
|
+
|
|
831
|
+
if (numValue < 0 && (key.includes("Length") || key.includes("Items"))) {
|
|
832
|
+
throw new Error(`"${key}" cannot be negative`);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
constraints[key] = numValue;
|
|
836
|
+
break;
|
|
837
|
+
|
|
838
|
+
case "pattern":
|
|
839
|
+
const regexPattern = this._parseRegexPattern(value);
|
|
840
|
+
if (!regexPattern) {
|
|
841
|
+
throw new Error(
|
|
842
|
+
`Pattern must be in regex format (/pattern/flags): "${value}"`
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
constraints.pattern = regexPattern;
|
|
846
|
+
break;
|
|
847
|
+
|
|
848
|
+
case "unique":
|
|
849
|
+
if (!this._patterns.booleanValue.test(value)) {
|
|
850
|
+
throw new Error(
|
|
851
|
+
`"unique" must be "true" or "false", got: "${value}"`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
constraints.unique = value.toLowerCase() === "true";
|
|
855
|
+
break;
|
|
856
|
+
|
|
857
|
+
default:
|
|
858
|
+
throw new Error(`Unknown constraint key: "${key}"`);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Enhanced error message extraction
|
|
864
|
+
*/
|
|
865
|
+
private static _getErrorMessage(error: unknown): string {
|
|
866
|
+
if (error instanceof Error) {
|
|
867
|
+
return error.message;
|
|
868
|
+
}
|
|
869
|
+
if (typeof error === "string") {
|
|
870
|
+
return error;
|
|
871
|
+
}
|
|
872
|
+
return "Unknown error";
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// Enhanced public utility methods with stronger validation
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Check if a field type has constraints - enhanced validation
|
|
879
|
+
*/
|
|
880
|
+
static hasConstraints(fieldType: string): boolean {
|
|
881
|
+
if (!this._isValidInput(fieldType)) {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
const sanitized = this._sanitizeInput(fieldType);
|
|
886
|
+
const withoutModifiers = sanitized
|
|
887
|
+
.replace(this._patterns.optionalMarker, "")
|
|
888
|
+
.replace(this._patterns.requiredMarker, "");
|
|
889
|
+
|
|
890
|
+
return this._patterns.complexConstraint.test(withoutModifiers);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Extract base type without constraints - enhanced
|
|
895
|
+
*/
|
|
896
|
+
static getBaseType(fieldType: string): string {
|
|
897
|
+
if (!this._isValidInput(fieldType)) {
|
|
898
|
+
return "";
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
try {
|
|
902
|
+
const parsed = this.parseConstraints(fieldType);
|
|
903
|
+
return parsed.type;
|
|
904
|
+
} catch {
|
|
905
|
+
// Enhanced fallback with regex
|
|
906
|
+
const sanitized = this._sanitizeInput(fieldType);
|
|
907
|
+
return sanitized
|
|
908
|
+
.replace(/\([^)]*\)/, "")
|
|
909
|
+
.replace(this._patterns.optionalMarker, "")
|
|
910
|
+
.replace(this._patterns.requiredMarker, "")
|
|
911
|
+
.trim();
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Check if field type is optional - enhanced
|
|
917
|
+
*/
|
|
918
|
+
static isOptional(fieldType: string): boolean {
|
|
919
|
+
return this._isValidInput(fieldType) && this._hasOptionalMarker(fieldType);
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* Check if field type is required - enhanced
|
|
924
|
+
*/
|
|
925
|
+
static isRequired(fieldType: string): boolean {
|
|
926
|
+
return this._isValidInput(fieldType) && this._hasRequiredMarker(fieldType);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* Check if field type is an array - enhanced
|
|
931
|
+
*/
|
|
932
|
+
static isArrayType(fieldType: string): boolean {
|
|
933
|
+
if (!this._isValidInput(fieldType)) {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
try {
|
|
938
|
+
const parsed = this.parseConstraints(fieldType);
|
|
939
|
+
return this._isArrayType(parsed.type);
|
|
940
|
+
} catch {
|
|
941
|
+
return false;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Get element type for array types - enhanced
|
|
947
|
+
*/
|
|
948
|
+
static getElementType(fieldType: string): string {
|
|
949
|
+
if (!this._isValidInput(fieldType)) {
|
|
950
|
+
return fieldType;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
try {
|
|
954
|
+
const parsed = this.parseConstraints(fieldType);
|
|
955
|
+
if (this._isArrayType(parsed.type)) {
|
|
956
|
+
return parsed.type.replace(/\[\]$/, "");
|
|
957
|
+
}
|
|
958
|
+
return parsed.type;
|
|
959
|
+
} catch {
|
|
960
|
+
return fieldType;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* Enhanced constraint validation
|
|
966
|
+
*/
|
|
967
|
+
static validateConstraints(constraints: any, type: string): string[] {
|
|
968
|
+
if (!constraints || typeof constraints !== "object") {
|
|
969
|
+
return [];
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
const errors: string[] = [];
|
|
973
|
+
|
|
974
|
+
try {
|
|
975
|
+
// Enhanced min/max validation
|
|
976
|
+
this._validateMinMaxRelationship(constraints);
|
|
977
|
+
|
|
978
|
+
// Enhanced type-specific validation
|
|
979
|
+
this._validateTypeSpecificConstraints(constraints, type, errors);
|
|
980
|
+
|
|
981
|
+
// Enhanced regex pattern validation
|
|
982
|
+
if (constraints.pattern && !(constraints.pattern instanceof RegExp)) {
|
|
983
|
+
errors.push("Pattern constraint must be a RegExp object");
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// Enhanced negative value validation
|
|
987
|
+
this._validateNegativeConstraints(constraints, errors);
|
|
988
|
+
} catch (error) {
|
|
989
|
+
errors.push(
|
|
990
|
+
`Constraint validation error: ${this._getErrorMessage(error)}`
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
return errors;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* Validate type-specific constraints
|
|
999
|
+
*/
|
|
1000
|
+
private static _validateTypeSpecificConstraints(
|
|
1001
|
+
constraints: any,
|
|
1002
|
+
type: string,
|
|
1003
|
+
errors: string[]
|
|
1004
|
+
): void {
|
|
1005
|
+
if (
|
|
1006
|
+
type === "positive" &&
|
|
1007
|
+
constraints.min !== undefined &&
|
|
1008
|
+
constraints.min < 0
|
|
1009
|
+
) {
|
|
1010
|
+
errors.push("Positive type cannot have negative minimum value");
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
if (
|
|
1014
|
+
type === "negative" &&
|
|
1015
|
+
constraints.max !== undefined &&
|
|
1016
|
+
constraints.max > 0
|
|
1017
|
+
) {
|
|
1018
|
+
errors.push("Negative type cannot have positive maximum value");
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* Validate negative constraints
|
|
1024
|
+
*/
|
|
1025
|
+
private static _validateNegativeConstraints(
|
|
1026
|
+
constraints: any,
|
|
1027
|
+
errors: string[]
|
|
1028
|
+
): void {
|
|
1029
|
+
const lengthKeys = [
|
|
1030
|
+
ConstraintType.MinLength,
|
|
1031
|
+
ConstraintType.MaxLength,
|
|
1032
|
+
ConstraintType.MinItems,
|
|
1033
|
+
ConstraintType.MaxItems,
|
|
1034
|
+
];
|
|
1035
|
+
|
|
1036
|
+
lengthKeys.forEach((key) => {
|
|
1037
|
+
if (constraints[key] !== undefined && constraints[key] < 0) {
|
|
1038
|
+
errors.push(`${key} cannot be negative`);
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* Enhanced constraint merging
|
|
1045
|
+
*/
|
|
1046
|
+
static mergeConstraints(baseOptions: any, constraints: any): any {
|
|
1047
|
+
if (!baseOptions && !constraints) {
|
|
1048
|
+
return {};
|
|
1049
|
+
}
|
|
1050
|
+
if (!baseOptions) {
|
|
1051
|
+
return this._deepCloneObject(constraints);
|
|
1052
|
+
}
|
|
1053
|
+
if (!constraints) {
|
|
1054
|
+
return this._deepCloneObject(baseOptions);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
const merged = { ...baseOptions };
|
|
1058
|
+
|
|
1059
|
+
// Enhanced merging with conflict resolution
|
|
1060
|
+
for (const [key, value] of Object.entries(constraints)) {
|
|
1061
|
+
if (value instanceof RegExp) {
|
|
1062
|
+
merged[key] = new RegExp(value.source, value.flags);
|
|
1063
|
+
} else if (typeof value === "object" && value !== null) {
|
|
1064
|
+
merged[key] = { ...value };
|
|
1065
|
+
} else {
|
|
1066
|
+
merged[key] = value;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
return merged;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Deep clone utility for objects
|
|
1075
|
+
*/
|
|
1076
|
+
private static _deepCloneObject(obj: any): any {
|
|
1077
|
+
if (!obj || typeof obj !== "object") {
|
|
1078
|
+
return obj;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
const cloned: any = {};
|
|
1082
|
+
|
|
1083
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1084
|
+
if (value instanceof RegExp) {
|
|
1085
|
+
cloned[key] = new RegExp(value.source, value.flags);
|
|
1086
|
+
} else if (typeof value === "object" && value !== null) {
|
|
1087
|
+
cloned[key] = { ...value };
|
|
1088
|
+
} else {
|
|
1089
|
+
cloned[key] = value;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
return cloned;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* Enhanced cache clearing with statistics reset
|
|
1098
|
+
*/
|
|
1099
|
+
static clearCache(): void {
|
|
1100
|
+
this._parseCache.clear();
|
|
1101
|
+
this._cacheHits = 0;
|
|
1102
|
+
this._cacheMisses = 0;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* Enhanced cache statistics with additional metrics
|
|
1107
|
+
*/
|
|
1108
|
+
static getCacheStats(): {
|
|
1109
|
+
size: number;
|
|
1110
|
+
hitRate: number;
|
|
1111
|
+
hits: number;
|
|
1112
|
+
misses: number;
|
|
1113
|
+
maxSize: number;
|
|
1114
|
+
efficiency: number;
|
|
1115
|
+
} {
|
|
1116
|
+
const total = this._cacheHits + this._cacheMisses;
|
|
1117
|
+
const hitRate = total > 0 ? this._cacheHits / total : 0;
|
|
1118
|
+
const efficiency = this._parseCache.size > 0 ? hitRate : 0;
|
|
1119
|
+
|
|
1120
|
+
return {
|
|
1121
|
+
size: this._parseCache.size,
|
|
1122
|
+
hitRate: Number(hitRate.toFixed(4)),
|
|
1123
|
+
hits: this._cacheHits,
|
|
1124
|
+
misses: this._cacheMisses,
|
|
1125
|
+
maxSize: this._maxCacheSize,
|
|
1126
|
+
efficiency: Number(efficiency.toFixed(4)),
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Enhanced constraint description with better formatting
|
|
1132
|
+
*/
|
|
1133
|
+
static getConstraintDescription(constraints: any, _type?: string): string {
|
|
1134
|
+
if (!constraints || typeof constraints !== "object") {
|
|
1135
|
+
return "";
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
const descriptions: string[] = [];
|
|
1139
|
+
|
|
1140
|
+
try {
|
|
1141
|
+
const constraintKeys = [
|
|
1142
|
+
ConstraintType.Min,
|
|
1143
|
+
ConstraintType.Max,
|
|
1144
|
+
ConstraintType.MinLength,
|
|
1145
|
+
ConstraintType.MaxLength,
|
|
1146
|
+
ConstraintType.MinItems,
|
|
1147
|
+
ConstraintType.MaxItems,
|
|
1148
|
+
] as const;
|
|
1149
|
+
|
|
1150
|
+
constraintKeys.forEach((key) => {
|
|
1151
|
+
if (
|
|
1152
|
+
constraints[key] !== undefined &&
|
|
1153
|
+
Number.isFinite(constraints[key])
|
|
1154
|
+
) {
|
|
1155
|
+
descriptions.push(`${key}: ${constraints[key]}`);
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
if (constraints.pattern instanceof RegExp) {
|
|
1160
|
+
const flags = constraints.pattern.flags
|
|
1161
|
+
? `/${constraints.pattern.flags}`
|
|
1162
|
+
: "";
|
|
1163
|
+
descriptions.push(`pattern: /${constraints.pattern.source}${flags}`);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
if (constraints.unique === true) {
|
|
1167
|
+
descriptions.push("unique: true");
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// Enhanced description formatting
|
|
1171
|
+
return descriptions.length > 0 ? `(${descriptions.join(", ")})` : "";
|
|
1172
|
+
} catch (error) {
|
|
1173
|
+
return `(invalid constraints: ${this._getErrorMessage(error)})`;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/**
|
|
1178
|
+
* Enhanced complex constraint parsing (public interface)
|
|
1179
|
+
*/
|
|
1180
|
+
static parseComplexConstraints(constraintStr: string): any {
|
|
1181
|
+
if (!this._isValidInput(constraintStr)) {
|
|
1182
|
+
throw new Error("Invalid constraint string: must be a non-empty string");
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
try {
|
|
1186
|
+
return this._parseComplexConstraints(constraintStr);
|
|
1187
|
+
} catch (error) {
|
|
1188
|
+
throw new Error(
|
|
1189
|
+
`Failed to parse complex constraints "${constraintStr}": ${this._getErrorMessage(error)}`
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
// Additional enhanced utility methods
|
|
1195
|
+
|
|
1196
|
+
/**
|
|
1197
|
+
* Validate field type format comprehensively
|
|
1198
|
+
*/
|
|
1199
|
+
static isValidFieldType(fieldType: string): boolean {
|
|
1200
|
+
if (!this._isValidInput(fieldType)) {
|
|
1201
|
+
return false;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
try {
|
|
1205
|
+
this.parseConstraints(fieldType);
|
|
1206
|
+
return true;
|
|
1207
|
+
} catch {
|
|
1208
|
+
return false;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* Extract all modifiers from field type
|
|
1214
|
+
*/
|
|
1215
|
+
static getFieldTypeModifiers(fieldType: string): {
|
|
1216
|
+
optional: boolean;
|
|
1217
|
+
required: boolean;
|
|
1218
|
+
hasConstraints: boolean;
|
|
1219
|
+
} {
|
|
1220
|
+
if (!this._isValidInput(fieldType)) {
|
|
1221
|
+
return { optional: false, required: false, hasConstraints: false };
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
try {
|
|
1225
|
+
const parsed = this.parseConstraints(fieldType);
|
|
1226
|
+
return {
|
|
1227
|
+
optional: parsed.optional,
|
|
1228
|
+
required: parsed.required,
|
|
1229
|
+
hasConstraints: Object.keys(parsed.constraints).length > 0,
|
|
1230
|
+
};
|
|
1231
|
+
} catch {
|
|
1232
|
+
return {
|
|
1233
|
+
optional: this.isOptional(fieldType),
|
|
1234
|
+
required: this.isRequired(fieldType),
|
|
1235
|
+
hasConstraints: this.hasConstraints(fieldType),
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* Normalize field type string
|
|
1242
|
+
*/
|
|
1243
|
+
static normalizeFieldType(fieldType: string): string {
|
|
1244
|
+
if (!this._isValidInput(fieldType)) {
|
|
1245
|
+
return "";
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
try {
|
|
1249
|
+
const parsed = this.parseConstraints(fieldType);
|
|
1250
|
+
let normalized = parsed.type;
|
|
1251
|
+
|
|
1252
|
+
// Add constraints back if they exist
|
|
1253
|
+
if (Object.keys(parsed.constraints).length > 0) {
|
|
1254
|
+
const constraintDesc = this._formatConstraintsForType(
|
|
1255
|
+
parsed.constraints
|
|
1256
|
+
);
|
|
1257
|
+
if (constraintDesc) {
|
|
1258
|
+
normalized += `(${constraintDesc})`;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// Add modifiers back
|
|
1263
|
+
if (parsed.required) {
|
|
1264
|
+
normalized += "!";
|
|
1265
|
+
}
|
|
1266
|
+
if (parsed.optional) {
|
|
1267
|
+
normalized += "?";
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
return normalized;
|
|
1271
|
+
} catch {
|
|
1272
|
+
return this._sanitizeInput(fieldType);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Format constraints for type reconstruction
|
|
1278
|
+
*/
|
|
1279
|
+
private static _formatConstraintsForType(constraints: any): string {
|
|
1280
|
+
if (!constraints || typeof constraints !== "object") {
|
|
1281
|
+
return "";
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
const parts: string[] = [];
|
|
1285
|
+
|
|
1286
|
+
// Handle regex pattern
|
|
1287
|
+
if (constraints.pattern instanceof RegExp) {
|
|
1288
|
+
const flags = constraints.pattern.flags || "";
|
|
1289
|
+
parts.push(`/${constraints.pattern.source}/${flags}`);
|
|
1290
|
+
return parts.join(";");
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// Handle min/max pairs
|
|
1294
|
+
if (constraints.min !== undefined && constraints.max !== undefined) {
|
|
1295
|
+
parts.push(`${constraints.min},${constraints.max}`);
|
|
1296
|
+
} else if (constraints.min !== undefined) {
|
|
1297
|
+
parts.push(`${constraints.min},`);
|
|
1298
|
+
} else if (constraints.max !== undefined) {
|
|
1299
|
+
parts.push(`${constraints.max}`);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// Handle length constraints
|
|
1303
|
+
if (
|
|
1304
|
+
constraints.minLength !== undefined &&
|
|
1305
|
+
constraints.maxLength !== undefined
|
|
1306
|
+
) {
|
|
1307
|
+
if (parts.length === 0) {
|
|
1308
|
+
parts.push(`${constraints.minLength},${constraints.maxLength}`);
|
|
1309
|
+
} else {
|
|
1310
|
+
parts.push(
|
|
1311
|
+
`minLength:${constraints.minLength};maxLength:${constraints.maxLength}`
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// Handle items constraints
|
|
1317
|
+
if (
|
|
1318
|
+
constraints.minItems !== undefined &&
|
|
1319
|
+
constraints.maxItems !== undefined
|
|
1320
|
+
) {
|
|
1321
|
+
if (parts.length === 0) {
|
|
1322
|
+
parts.push(`${constraints.minItems},${constraints.maxItems}`);
|
|
1323
|
+
} else {
|
|
1324
|
+
parts.push(
|
|
1325
|
+
`minItems:${constraints.minItems};maxItems:${constraints.maxItems}`
|
|
1326
|
+
);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// Handle unique
|
|
1331
|
+
if (constraints.unique === true) {
|
|
1332
|
+
parts.push("unique:true");
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
return parts.join(";");
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* Performance monitoring utilities
|
|
1340
|
+
*/
|
|
1341
|
+
static getParsingPerformance(): {
|
|
1342
|
+
totalParses: number;
|
|
1343
|
+
cacheHitRatio: number;
|
|
1344
|
+
averageParseTime: number;
|
|
1345
|
+
memoryUsage: number;
|
|
1346
|
+
} {
|
|
1347
|
+
const total = this._cacheHits + this._cacheMisses;
|
|
1348
|
+
const hitRatio = total > 0 ? this._cacheHits / total : 0;
|
|
1349
|
+
|
|
1350
|
+
return {
|
|
1351
|
+
totalParses: total,
|
|
1352
|
+
cacheHitRatio: Number(hitRatio.toFixed(4)),
|
|
1353
|
+
averageParseTime: 0, // Would need instrumentation
|
|
1354
|
+
memoryUsage: this._parseCache.size * 100, // Rough estimate
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* Optimize cache by removing least recently used entries
|
|
1360
|
+
*/
|
|
1361
|
+
static optimizeCache(): void {
|
|
1362
|
+
if (this._parseCache.size <= this._maxCacheSize * 0.8) {
|
|
1363
|
+
return; // No optimization needed
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
const entries = Array.from(this._parseCache.entries());
|
|
1367
|
+
const keepSize = Math.floor(this._maxCacheSize * 0.6);
|
|
1368
|
+
|
|
1369
|
+
// Keep most recent entries (simple LRU approximation)
|
|
1370
|
+
this._parseCache.clear();
|
|
1371
|
+
|
|
1372
|
+
entries.slice(-keepSize).forEach(([key, value]) => {
|
|
1373
|
+
this._parseCache.set(key, value);
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* Validate constraint compatibility with field type
|
|
1379
|
+
*/
|
|
1380
|
+
static validateConstraintCompatibility(
|
|
1381
|
+
fieldType: string,
|
|
1382
|
+
constraints: any
|
|
1383
|
+
): { valid: boolean; errors: string[] } {
|
|
1384
|
+
const errors: string[] = [];
|
|
1385
|
+
|
|
1386
|
+
if (!this._isValidInput(fieldType)) {
|
|
1387
|
+
errors.push("Invalid field type");
|
|
1388
|
+
return { valid: false, errors };
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
if (!constraints || typeof constraints !== "object") {
|
|
1392
|
+
return { valid: true, errors: [] };
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
try {
|
|
1396
|
+
const parsed = this.parseConstraints(fieldType);
|
|
1397
|
+
const baseType = parsed.type;
|
|
1398
|
+
|
|
1399
|
+
// Check string-specific constraints
|
|
1400
|
+
if (!this._isStringType(baseType)) {
|
|
1401
|
+
if (
|
|
1402
|
+
constraints.minLength !== undefined ||
|
|
1403
|
+
constraints.maxLength !== undefined
|
|
1404
|
+
) {
|
|
1405
|
+
errors.push("Length constraints are only valid for string types");
|
|
1406
|
+
}
|
|
1407
|
+
if (constraints.pattern !== undefined) {
|
|
1408
|
+
errors.push("Pattern constraints are only valid for string types");
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
// Check array-specific constraints
|
|
1413
|
+
if (!this._isArrayType(baseType)) {
|
|
1414
|
+
if (
|
|
1415
|
+
constraints.minItems !== undefined ||
|
|
1416
|
+
constraints.maxItems !== undefined
|
|
1417
|
+
) {
|
|
1418
|
+
errors.push("Item constraints are only valid for array types");
|
|
1419
|
+
}
|
|
1420
|
+
if (constraints.unique !== undefined) {
|
|
1421
|
+
errors.push("Unique constraints are only valid for array types");
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// Check numeric-specific constraints
|
|
1426
|
+
const numericTypes = ["number", "integer", "positive", "negative"];
|
|
1427
|
+
if (!numericTypes.some((t) => baseType.includes(t))) {
|
|
1428
|
+
if (constraints.min !== undefined || constraints.max !== undefined) {
|
|
1429
|
+
errors.push("Min/Max constraints are only valid for numeric types");
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
} catch (error) {
|
|
1433
|
+
errors.push(`Type parsing error: ${this._getErrorMessage(error)}`);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
return { valid: errors.length === 0, errors };
|
|
1437
|
+
}
|
|
1438
|
+
}
|