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,1033 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var InterfaceSchema = require('../schema/mode/interfaces/InterfaceSchema.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Enhanced schema modification utilities - transform, combine, and manipulate schemas
|
|
7
|
+
*/
|
|
8
|
+
class Mod {
|
|
9
|
+
/**
|
|
10
|
+
* Safely access schema internals with proper typing
|
|
11
|
+
*/
|
|
12
|
+
static getSchemaInternals(schema) {
|
|
13
|
+
return {
|
|
14
|
+
definition: schema
|
|
15
|
+
.definition,
|
|
16
|
+
options: schema.options || {},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Merge multiple schemas into a single schema
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const UserSchema = Interface({ id: "number", name: "string" });
|
|
24
|
+
* const ProfileSchema = Interface({ bio: "string?", avatar: "url?" });
|
|
25
|
+
*
|
|
26
|
+
* const MergedSchema = Mod.merge(UserSchema, ProfileSchema);
|
|
27
|
+
* // Result: { id: number, name: string, bio?: string, avatar?: string }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
static merge(schema1, schema2) {
|
|
31
|
+
const { definition: def1 } = this.getSchemaInternals(schema1);
|
|
32
|
+
const { definition: def2 } = this.getSchemaInternals(schema2);
|
|
33
|
+
const mergedDefinition = {
|
|
34
|
+
...def1,
|
|
35
|
+
...def2,
|
|
36
|
+
};
|
|
37
|
+
const { options: options1 } = this.getSchemaInternals(schema1);
|
|
38
|
+
const { options: options2 } = this.getSchemaInternals(schema2);
|
|
39
|
+
const mergedOptions = { ...options1, ...options2 };
|
|
40
|
+
return new InterfaceSchema.InterfaceSchema(mergedDefinition, mergedOptions);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Merge multiple schemas with conflict resolution
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const schema1 = Interface({ id: "number", name: "string" });
|
|
47
|
+
* const schema2 = Interface({ id: "uuid", email: "email" });
|
|
48
|
+
*
|
|
49
|
+
* const merged = Mod.mergeDeep(schema1, schema2, "second"); // id becomes "uuid"
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
static mergeDeep(schema1, schema2, strategy = "second") {
|
|
53
|
+
const def1 = schema1.definition;
|
|
54
|
+
const def2 = schema2.definition;
|
|
55
|
+
const mergedDefinition = { ...def1 };
|
|
56
|
+
for (const [key, value] of Object.entries(def2)) {
|
|
57
|
+
if (key in mergedDefinition) {
|
|
58
|
+
switch (strategy) {
|
|
59
|
+
case "first":
|
|
60
|
+
// Keep first schema's value
|
|
61
|
+
break;
|
|
62
|
+
case "second":
|
|
63
|
+
mergedDefinition[key] = value;
|
|
64
|
+
break;
|
|
65
|
+
case "merge":
|
|
66
|
+
// Attempt to merge if both are objects
|
|
67
|
+
if (typeof mergedDefinition[key] === "object" &&
|
|
68
|
+
typeof value === "object") {
|
|
69
|
+
mergedDefinition[key] = { ...mergedDefinition[key], ...value };
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
mergedDefinition[key] = value;
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
mergedDefinition[key] = value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const options1 = schema1.options || {};
|
|
82
|
+
const options2 = schema2.options || {};
|
|
83
|
+
const mergedOptions = { ...options1, ...options2 };
|
|
84
|
+
return new InterfaceSchema.InterfaceSchema(mergedDefinition, mergedOptions);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Pick specific fields from a schema
|
|
88
|
+
*/
|
|
89
|
+
static pick(schema, keys) {
|
|
90
|
+
const { definition, options } = this.getSchemaInternals(schema);
|
|
91
|
+
const pickedDefinition = {};
|
|
92
|
+
for (const key of keys) {
|
|
93
|
+
const keyStr = key;
|
|
94
|
+
if (keyStr in definition) {
|
|
95
|
+
pickedDefinition[keyStr] = definition[keyStr];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return new InterfaceSchema.InterfaceSchema(pickedDefinition, options);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Omit specific fields from a schema
|
|
102
|
+
*/
|
|
103
|
+
static omit(schema, keys) {
|
|
104
|
+
const { definition, options } = this.getSchemaInternals(schema);
|
|
105
|
+
const omittedDefinition = { ...definition };
|
|
106
|
+
for (const key of keys) {
|
|
107
|
+
const keyStr = key;
|
|
108
|
+
delete omittedDefinition[keyStr];
|
|
109
|
+
}
|
|
110
|
+
const newOptions = {
|
|
111
|
+
...options,
|
|
112
|
+
_omittedFields: [
|
|
113
|
+
...(options._omittedFields || []),
|
|
114
|
+
...keys.map((k) => k),
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
return new InterfaceSchema.InterfaceSchema(omittedDefinition, newOptions);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Make all fields in a schema optional
|
|
121
|
+
*/
|
|
122
|
+
static partial(schema) {
|
|
123
|
+
const definition = schema.definition;
|
|
124
|
+
const options = schema.options || {};
|
|
125
|
+
const partialDefinition = {};
|
|
126
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
127
|
+
if (typeof value === "string" && !value.endsWith("?")) {
|
|
128
|
+
partialDefinition[key] = value + "?";
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
partialDefinition[key] = value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return new InterfaceSchema.InterfaceSchema(partialDefinition, options);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Make all fields in a schema required
|
|
138
|
+
*/
|
|
139
|
+
static required(schema) {
|
|
140
|
+
const definition = schema.definition;
|
|
141
|
+
const options = schema.options || {};
|
|
142
|
+
const requiredDefinition = {};
|
|
143
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
144
|
+
if (typeof value === "string" && value.endsWith("?")) {
|
|
145
|
+
requiredDefinition[key] = value.slice(0, -1);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
requiredDefinition[key] = value;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return new InterfaceSchema.InterfaceSchema(requiredDefinition, options);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Make specific fields optional in a schema without modifying field types
|
|
155
|
+
*
|
|
156
|
+
* This method allows you to selectively make certain fields optional while keeping
|
|
157
|
+
* all other fields required. It's particularly useful when you want to create
|
|
158
|
+
* flexible versions of strict schemas for different use cases (e.g., partial updates,
|
|
159
|
+
* form validation, API endpoints with optional parameters).
|
|
160
|
+
*
|
|
161
|
+
* The method works with both primitive types and nested objects, properly handling
|
|
162
|
+
* the optional nature at the validation level while maintaining type safety.
|
|
163
|
+
*
|
|
164
|
+
* @param schema - The source schema to modify
|
|
165
|
+
* @param keys - Array of field names to make optional
|
|
166
|
+
* @returns A new schema with specified fields made optional
|
|
167
|
+
*
|
|
168
|
+
* @example Making primitive fields optional
|
|
169
|
+
* ```typescript
|
|
170
|
+
* const UserSchema = Interface({
|
|
171
|
+
* id: "number",
|
|
172
|
+
* name: "string",
|
|
173
|
+
* email: "email",
|
|
174
|
+
* phone: "string"
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* const FlexibleUserSchema = Mod.makeOptional(UserSchema, ["email", "phone"]);
|
|
178
|
+
*
|
|
179
|
+
* // Now accepts both:
|
|
180
|
+
* FlexibleUserSchema.parse({ id: 1, name: "John" }); // ✅ email and phone optional
|
|
181
|
+
* FlexibleUserSchema.parse({ id: 1, name: "John", email: "john@example.com" }); // ✅
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @example Making nested objects optional
|
|
185
|
+
* ```typescript
|
|
186
|
+
* const ProfileSchema = Interface({
|
|
187
|
+
* id: "number",
|
|
188
|
+
* name: "string",
|
|
189
|
+
* preferences: {
|
|
190
|
+
* theme: "light|dark",
|
|
191
|
+
* notifications: "boolean",
|
|
192
|
+
* language: "en|es|fr"
|
|
193
|
+
* },
|
|
194
|
+
* settings: {
|
|
195
|
+
* privacy: "public|private",
|
|
196
|
+
* newsletter: "boolean"
|
|
197
|
+
* }
|
|
198
|
+
* });
|
|
199
|
+
*
|
|
200
|
+
* const FlexibleProfileSchema = Mod.makeOptional(ProfileSchema, ["preferences", "settings"]);
|
|
201
|
+
*
|
|
202
|
+
* // Now accepts:
|
|
203
|
+
* FlexibleProfileSchema.parse({ id: 1, name: "John" }); // ✅ nested objects optional
|
|
204
|
+
* FlexibleProfileSchema.parse({
|
|
205
|
+
* id: 1,
|
|
206
|
+
* name: "John",
|
|
207
|
+
* preferences: { theme: "dark", notifications: true, language: "en" }
|
|
208
|
+
* }); // ✅
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @example Use case: API endpoints with optional parameters
|
|
212
|
+
* ```typescript
|
|
213
|
+
* const CreateUserSchema = Interface({
|
|
214
|
+
* name: "string",
|
|
215
|
+
* email: "email",
|
|
216
|
+
* password: "string",
|
|
217
|
+
* role: "admin|user|moderator",
|
|
218
|
+
* department: "string",
|
|
219
|
+
* startDate: "date"
|
|
220
|
+
* });
|
|
221
|
+
*
|
|
222
|
+
* // For user registration (minimal required fields)
|
|
223
|
+
* const RegisterSchema = Mod.makeOptional(CreateUserSchema, ["role", "department", "startDate"]);
|
|
224
|
+
*
|
|
225
|
+
* // For admin creation (all fields required)
|
|
226
|
+
* const AdminCreateSchema = CreateUserSchema;
|
|
227
|
+
*
|
|
228
|
+
* // For profile updates (most fields optional)
|
|
229
|
+
* const UpdateProfileSchema = Mod.makeOptional(CreateUserSchema, ["password", "role", "department", "startDate"]);
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
static makeOptional(schema, keys) {
|
|
233
|
+
const { definition, options } = this.getSchemaInternals(schema);
|
|
234
|
+
// Create new definition with specified fields made optional
|
|
235
|
+
const newDefinition = { ...definition };
|
|
236
|
+
for (const key of keys) {
|
|
237
|
+
const keyStr = key;
|
|
238
|
+
if (keyStr in newDefinition) {
|
|
239
|
+
const fieldType = newDefinition[keyStr];
|
|
240
|
+
if (typeof fieldType === "string" && !fieldType.endsWith("?")) {
|
|
241
|
+
newDefinition[keyStr] = fieldType + "?";
|
|
242
|
+
}
|
|
243
|
+
else if (typeof fieldType === "object") {
|
|
244
|
+
// For nested objects, we need to wrap them in an optional schema interface
|
|
245
|
+
// This tells the validation system that the entire nested object is optional
|
|
246
|
+
newDefinition[keyStr] = {
|
|
247
|
+
schema: fieldType,
|
|
248
|
+
optional: true,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return new InterfaceSchema.InterfaceSchema(newDefinition, options);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Extend a schema with additional fields
|
|
257
|
+
*/
|
|
258
|
+
static extend(schema, extension) {
|
|
259
|
+
const definition = schema.definition;
|
|
260
|
+
const options = schema.options || {};
|
|
261
|
+
const extendedDefinition = {
|
|
262
|
+
...definition,
|
|
263
|
+
...extension,
|
|
264
|
+
};
|
|
265
|
+
return new InterfaceSchema.InterfaceSchema(extendedDefinition, options);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Create a deep partial version of a schema (makes ALL fields optional recursively)
|
|
269
|
+
*
|
|
270
|
+
* Unlike the regular `partial()` method which only makes top-level fields optional,
|
|
271
|
+
* `deepPartial()` recursively traverses the entire schema structure and makes every
|
|
272
|
+
* field at every nesting level optional. This is particularly useful for update
|
|
273
|
+
* operations, patch APIs, or form validation where users might only provide
|
|
274
|
+
* partial data at any level of nesting.
|
|
275
|
+
*
|
|
276
|
+
* @param schema - The source schema to make deeply partial
|
|
277
|
+
* @returns A new schema where all fields at all levels are optional
|
|
278
|
+
*
|
|
279
|
+
* @example Basic deep partial transformation
|
|
280
|
+
* ```typescript
|
|
281
|
+
* const UserSchema = Interface({
|
|
282
|
+
* id: "number",
|
|
283
|
+
* name: "string",
|
|
284
|
+
* profile: {
|
|
285
|
+
* bio: "string",
|
|
286
|
+
* avatar: "string",
|
|
287
|
+
* social: {
|
|
288
|
+
* twitter: "string",
|
|
289
|
+
* linkedin: "string"
|
|
290
|
+
* }
|
|
291
|
+
* }
|
|
292
|
+
* });
|
|
293
|
+
*
|
|
294
|
+
* const DeepPartialSchema = Mod.deepPartial(UserSchema);
|
|
295
|
+
*
|
|
296
|
+
* // All of these are now valid:
|
|
297
|
+
* DeepPartialSchema.parse({}); // ✅ Everything optional
|
|
298
|
+
* DeepPartialSchema.parse({ id: 1 }); // ✅ Only id provided
|
|
299
|
+
* DeepPartialSchema.parse({
|
|
300
|
+
* profile: {
|
|
301
|
+
* bio: "Developer"
|
|
302
|
+
* }
|
|
303
|
+
* }); // ✅ Partial nested data
|
|
304
|
+
* DeepPartialSchema.parse({
|
|
305
|
+
* profile: {
|
|
306
|
+
* social: {
|
|
307
|
+
* twitter: "@john"
|
|
308
|
+
* }
|
|
309
|
+
* }
|
|
310
|
+
* }); // ✅ Deep nested partial data
|
|
311
|
+
* ```
|
|
312
|
+
*
|
|
313
|
+
* @example Use case: API PATCH endpoints
|
|
314
|
+
* ```typescript
|
|
315
|
+
* const ArticleSchema = Interface({
|
|
316
|
+
* id: "number",
|
|
317
|
+
* title: "string",
|
|
318
|
+
* content: "string",
|
|
319
|
+
* metadata: {
|
|
320
|
+
* tags: "string[]",
|
|
321
|
+
* category: "string",
|
|
322
|
+
* seo: {
|
|
323
|
+
* title: "string",
|
|
324
|
+
* description: "string",
|
|
325
|
+
* keywords: "string[]"
|
|
326
|
+
* }
|
|
327
|
+
* },
|
|
328
|
+
* author: {
|
|
329
|
+
* id: "number",
|
|
330
|
+
* name: "string"
|
|
331
|
+
* }
|
|
332
|
+
* });
|
|
333
|
+
*
|
|
334
|
+
* // For PATCH /articles/:id - allow partial updates at any level
|
|
335
|
+
* const PatchArticleSchema = Mod.deepPartial(ArticleSchema);
|
|
336
|
+
*
|
|
337
|
+
* // Users can update just the SEO title:
|
|
338
|
+
* PatchArticleSchema.parse({
|
|
339
|
+
* metadata: {
|
|
340
|
+
* seo: {
|
|
341
|
+
* title: "New SEO Title"
|
|
342
|
+
* }
|
|
343
|
+
* }
|
|
344
|
+
* }); // ✅
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* @example Difference from regular partial()
|
|
348
|
+
* ```typescript
|
|
349
|
+
* const NestedSchema = Interface({
|
|
350
|
+
* user: {
|
|
351
|
+
* name: "string",
|
|
352
|
+
* email: "email"
|
|
353
|
+
* }
|
|
354
|
+
* });
|
|
355
|
+
*
|
|
356
|
+
* const RegularPartial = Mod.partial(NestedSchema);
|
|
357
|
+
* // Type: { user?: { name: string, email: string } }
|
|
358
|
+
* // user is optional, but if provided, name and email are required
|
|
359
|
+
*
|
|
360
|
+
* const DeepPartial = Mod.deepPartial(NestedSchema);
|
|
361
|
+
* // Type: { user?: { name?: string, email?: string } }
|
|
362
|
+
* // user is optional, and if provided, name and email are also optional
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
static deepPartial(schema) {
|
|
366
|
+
const definition = schema.definition;
|
|
367
|
+
const options = schema.options || {};
|
|
368
|
+
const deepPartialDefinition = {};
|
|
369
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
370
|
+
if (typeof value === "object" && value !== null) {
|
|
371
|
+
// Recursively make nested objects partial
|
|
372
|
+
const nestedSchema = new InterfaceSchema.InterfaceSchema(value, {});
|
|
373
|
+
const partialNested = this.deepPartial(nestedSchema);
|
|
374
|
+
// Make the nested object field optional by wrapping it
|
|
375
|
+
deepPartialDefinition[key] = {
|
|
376
|
+
schema: partialNested.definition,
|
|
377
|
+
optional: true,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
else if (typeof value === "string" && !value.endsWith("?")) {
|
|
381
|
+
deepPartialDefinition[key] = value + "?";
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
deepPartialDefinition[key] = value;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return new InterfaceSchema.InterfaceSchema(deepPartialDefinition, options);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Transform field types using a mapper function
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* const UserSchema = Interface({ id: "number", name: "string" });
|
|
394
|
+
* const StringifiedSchema = Mod.transform(UserSchema, (type) =>
|
|
395
|
+
* type.replace("number", "string")
|
|
396
|
+
* );
|
|
397
|
+
* // Result: { id: string, name: string }
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
static transform(schema, mapper) {
|
|
401
|
+
const definition = schema.definition;
|
|
402
|
+
const options = schema.options || {};
|
|
403
|
+
const transformedDefinition = {};
|
|
404
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
405
|
+
if (typeof value === "string") {
|
|
406
|
+
transformedDefinition[key] = mapper(value, key);
|
|
407
|
+
}
|
|
408
|
+
else if (typeof value === "object" && value !== null) {
|
|
409
|
+
// Recursively transform nested objects
|
|
410
|
+
const nestedSchema = new InterfaceSchema.InterfaceSchema(value, {});
|
|
411
|
+
const transformedNested = this.transform(nestedSchema, mapper);
|
|
412
|
+
transformedDefinition[key] = transformedNested.definition;
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
transformedDefinition[key] = value;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return new InterfaceSchema.InterfaceSchema(transformedDefinition, options);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Rename fields in a schema
|
|
422
|
+
* @example
|
|
423
|
+
* ```typescript
|
|
424
|
+
* const UserSchema = Interface({ user_id: "number", user_name: "string" });
|
|
425
|
+
* const RenamedSchema = Mod.rename(UserSchema, {
|
|
426
|
+
* user_id: "id",
|
|
427
|
+
* user_name: "name"
|
|
428
|
+
* });
|
|
429
|
+
* // Result: { id: number, name: string }
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
static rename(schema, fieldMap) {
|
|
433
|
+
const definition = schema.definition;
|
|
434
|
+
const options = schema.options || {};
|
|
435
|
+
const renamedDefinition = {};
|
|
436
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
437
|
+
const newKey = fieldMap[key] || key;
|
|
438
|
+
renamedDefinition[newKey] = value;
|
|
439
|
+
}
|
|
440
|
+
return new InterfaceSchema.InterfaceSchema(renamedDefinition, options);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Create a schema with default values that are automatically applied during validation
|
|
444
|
+
*
|
|
445
|
+
* This method allows you to specify default values that will be automatically applied
|
|
446
|
+
* to fields when they are missing or undefined in the input data. This is particularly
|
|
447
|
+
* useful for API endpoints, form processing, and configuration objects where you want
|
|
448
|
+
* to ensure certain fields always have sensible default values.
|
|
449
|
+
*
|
|
450
|
+
* Default values are applied during the validation process, so they don't modify the
|
|
451
|
+
* original schema definition but are included in the validated output.
|
|
452
|
+
*
|
|
453
|
+
* @param schema - The source schema to add defaults to
|
|
454
|
+
* @param defaultValues - Object mapping field names to their default values
|
|
455
|
+
* @returns A new schema that applies default values during validation
|
|
456
|
+
*
|
|
457
|
+
* @example Basic default values
|
|
458
|
+
* ```typescript
|
|
459
|
+
* const UserSchema = Interface({
|
|
460
|
+
* id: "number",
|
|
461
|
+
* name: "string",
|
|
462
|
+
* role: "string?",
|
|
463
|
+
* active: "boolean?",
|
|
464
|
+
* createdAt: "date?"
|
|
465
|
+
* });
|
|
466
|
+
*
|
|
467
|
+
* const UserWithDefaults = Mod.defaults(UserSchema, {
|
|
468
|
+
* role: "user",
|
|
469
|
+
* active: true,
|
|
470
|
+
* createdAt: new Date()
|
|
471
|
+
* });
|
|
472
|
+
*
|
|
473
|
+
* const result = UserWithDefaults.parse({
|
|
474
|
+
* id: 1,
|
|
475
|
+
* name: "John Doe"
|
|
476
|
+
* // role, active, and createdAt will be filled with defaults
|
|
477
|
+
* });
|
|
478
|
+
*
|
|
479
|
+
* console.log(result.data);
|
|
480
|
+
* // {
|
|
481
|
+
* // id: 1,
|
|
482
|
+
* // name: "John Doe",
|
|
483
|
+
* // role: "user",
|
|
484
|
+
* // active: true,
|
|
485
|
+
* // createdAt: 2023-12-01T10:30:00.000Z
|
|
486
|
+
* // }
|
|
487
|
+
* ```
|
|
488
|
+
*
|
|
489
|
+
* @example API configuration with defaults
|
|
490
|
+
* ```typescript
|
|
491
|
+
* const ApiConfigSchema = Interface({
|
|
492
|
+
* host: "string",
|
|
493
|
+
* port: "number?",
|
|
494
|
+
* timeout: "number?",
|
|
495
|
+
* retries: "number?",
|
|
496
|
+
* ssl: "boolean?",
|
|
497
|
+
* compression: "boolean?"
|
|
498
|
+
* });
|
|
499
|
+
*
|
|
500
|
+
* const ApiConfigWithDefaults = Mod.defaults(ApiConfigSchema, {
|
|
501
|
+
* port: 3000,
|
|
502
|
+
* timeout: 5000,
|
|
503
|
+
* retries: 3,
|
|
504
|
+
* ssl: false,
|
|
505
|
+
* compression: true
|
|
506
|
+
* });
|
|
507
|
+
*
|
|
508
|
+
* // Users only need to provide the host
|
|
509
|
+
* const config = ApiConfigWithDefaults.parse({
|
|
510
|
+
* host: "api.example.com"
|
|
511
|
+
* });
|
|
512
|
+
* // All other fields get sensible defaults
|
|
513
|
+
* ```
|
|
514
|
+
*
|
|
515
|
+
* @example Form processing with defaults
|
|
516
|
+
* ```typescript
|
|
517
|
+
* const ProfileFormSchema = Interface({
|
|
518
|
+
* name: "string",
|
|
519
|
+
* email: "email",
|
|
520
|
+
* theme: "string?",
|
|
521
|
+
* notifications: "boolean?",
|
|
522
|
+
* language: "string?"
|
|
523
|
+
* });
|
|
524
|
+
*
|
|
525
|
+
* const ProfileWithDefaults = Mod.defaults(ProfileFormSchema, {
|
|
526
|
+
* theme: "light",
|
|
527
|
+
* notifications: true,
|
|
528
|
+
* language: "en"
|
|
529
|
+
* });
|
|
530
|
+
*
|
|
531
|
+
* // Form submissions get defaults for unchecked/unselected fields
|
|
532
|
+
* const profile = ProfileWithDefaults.parse({
|
|
533
|
+
* name: "Jane Smith",
|
|
534
|
+
* email: "jane@example.com"
|
|
535
|
+
* // theme, notifications, language get defaults
|
|
536
|
+
* });
|
|
537
|
+
* ```
|
|
538
|
+
*
|
|
539
|
+
* @example Conditional defaults based on environment
|
|
540
|
+
* ```typescript
|
|
541
|
+
* const AppConfigSchema = Interface({
|
|
542
|
+
* environment: "development|staging|production",
|
|
543
|
+
* debug: "boolean?",
|
|
544
|
+
* logLevel: "string?",
|
|
545
|
+
* cacheEnabled: "boolean?"
|
|
546
|
+
* });
|
|
547
|
+
*
|
|
548
|
+
* const isDevelopment = process.env.NODE_ENV === "development";
|
|
549
|
+
*
|
|
550
|
+
* const AppConfigWithDefaults = Mod.defaults(AppConfigSchema, {
|
|
551
|
+
* debug: isDevelopment,
|
|
552
|
+
* logLevel: isDevelopment ? "debug" : "info",
|
|
553
|
+
* cacheEnabled: !isDevelopment
|
|
554
|
+
* });
|
|
555
|
+
* ```
|
|
556
|
+
*/
|
|
557
|
+
static defaults(schema, defaultValues) {
|
|
558
|
+
const definition = schema.definition;
|
|
559
|
+
const options = schema.options || {};
|
|
560
|
+
// Store default values in options for the validation system to use
|
|
561
|
+
const defaultsOptions = {
|
|
562
|
+
...options,
|
|
563
|
+
defaults: {
|
|
564
|
+
...(options.defaults || {}),
|
|
565
|
+
...defaultValues,
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
return new InterfaceSchema.InterfaceSchema(definition, defaultsOptions);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Create a strict version of a schema that rejects any additional properties
|
|
572
|
+
*
|
|
573
|
+
* By default, ReliantType ignores extra properties in the input data (they're
|
|
574
|
+
* simply not included in the validated output). The `strict()` method changes this
|
|
575
|
+
* behavior to actively reject any properties that aren't defined in the schema,
|
|
576
|
+
* making validation fail with an error.
|
|
577
|
+
*
|
|
578
|
+
* This is useful for APIs where you want to ensure clients aren't sending
|
|
579
|
+
* unexpected data, form validation where extra fields indicate errors, or
|
|
580
|
+
* configuration parsing where unknown options should be flagged.
|
|
581
|
+
*
|
|
582
|
+
* @param schema - The source schema to make strict
|
|
583
|
+
* @returns A new schema that rejects additional properties
|
|
584
|
+
*
|
|
585
|
+
* @example Basic strict validation
|
|
586
|
+
* ```typescript
|
|
587
|
+
* const UserSchema = Interface({
|
|
588
|
+
* id: "number",
|
|
589
|
+
* name: "string",
|
|
590
|
+
* email: "email"
|
|
591
|
+
* });
|
|
592
|
+
*
|
|
593
|
+
* const StrictUserSchema = Mod.strict(UserSchema);
|
|
594
|
+
*
|
|
595
|
+
* // This will succeed
|
|
596
|
+
* StrictUserSchema.parse({
|
|
597
|
+
* id: 1,
|
|
598
|
+
* name: "John",
|
|
599
|
+
* email: "john@example.com"
|
|
600
|
+
* }); // ✅
|
|
601
|
+
*
|
|
602
|
+
* // This will fail due to extra property
|
|
603
|
+
* StrictUserSchema.parse({
|
|
604
|
+
* id: 1,
|
|
605
|
+
* name: "John",
|
|
606
|
+
* email: "john@example.com",
|
|
607
|
+
* age: 30 // ❌ Error: Unexpected properties: age
|
|
608
|
+
* });
|
|
609
|
+
* ```
|
|
610
|
+
*
|
|
611
|
+
* @example API endpoint validation
|
|
612
|
+
* ```typescript
|
|
613
|
+
* const CreatePostSchema = Interface({
|
|
614
|
+
* title: "string",
|
|
615
|
+
* content: "string",
|
|
616
|
+
* tags: "string[]?",
|
|
617
|
+
* published: "boolean?"
|
|
618
|
+
* });
|
|
619
|
+
*
|
|
620
|
+
* const StrictCreatePostSchema = Mod.strict(CreatePostSchema);
|
|
621
|
+
*
|
|
622
|
+
* // Protect against typos or malicious extra data
|
|
623
|
+
* app.post('/posts', (req, res) => {
|
|
624
|
+
* const result = StrictCreatePostSchema.safeParse(req.body);
|
|
625
|
+
*
|
|
626
|
+
* if (!result.success) {
|
|
627
|
+
* return res.status(400).json({
|
|
628
|
+
* error: "Invalid request data",
|
|
629
|
+
* details: result.errors
|
|
630
|
+
* });
|
|
631
|
+
* }
|
|
632
|
+
*
|
|
633
|
+
* // Guaranteed to only contain expected fields
|
|
634
|
+
* const post = result.data;
|
|
635
|
+
* });
|
|
636
|
+
* ```
|
|
637
|
+
*
|
|
638
|
+
* @example Configuration validation
|
|
639
|
+
* ```typescript
|
|
640
|
+
* const DatabaseConfigSchema = Interface({
|
|
641
|
+
* host: "string",
|
|
642
|
+
* port: "number",
|
|
643
|
+
* username: "string",
|
|
644
|
+
* password: "string",
|
|
645
|
+
* database: "string"
|
|
646
|
+
* });
|
|
647
|
+
*
|
|
648
|
+
* const StrictDatabaseConfig = Mod.strict(DatabaseConfigSchema);
|
|
649
|
+
*
|
|
650
|
+
* // Catch configuration typos early
|
|
651
|
+
* const config = StrictDatabaseConfig.parse({
|
|
652
|
+
* host: "localhost",
|
|
653
|
+
* port: 5432,
|
|
654
|
+
* username: "admin",
|
|
655
|
+
* password: "secret",
|
|
656
|
+
* database: "myapp",
|
|
657
|
+
* connectionTimeout: 5000 // ❌ Error: Unknown config option
|
|
658
|
+
* });
|
|
659
|
+
* ```
|
|
660
|
+
*
|
|
661
|
+
* @example Comparison with default behavior
|
|
662
|
+
* ```typescript
|
|
663
|
+
* const Schema = Interface({ name: "string" });
|
|
664
|
+
* const StrictSchema = Mod.strict(Schema);
|
|
665
|
+
*
|
|
666
|
+
* const input = { name: "John", extra: "ignored" };
|
|
667
|
+
*
|
|
668
|
+
* // Default behavior: extra properties ignored
|
|
669
|
+
* const defaultResult = Schema.parse(input);
|
|
670
|
+
* console.log(defaultResult); // { name: "John" } - extra property ignored
|
|
671
|
+
*
|
|
672
|
+
* // Strict behavior: extra properties cause error
|
|
673
|
+
* const strictResult = StrictSchema.safeParse(input);
|
|
674
|
+
* console.log(strictResult.success); // false
|
|
675
|
+
* console.log(strictResult.errors); // [{ message: "Unexpected properties: extra" }]
|
|
676
|
+
* ```
|
|
677
|
+
*/
|
|
678
|
+
static strict(schema) {
|
|
679
|
+
const definition = schema.definition;
|
|
680
|
+
const options = schema.options || {};
|
|
681
|
+
const strictOptions = {
|
|
682
|
+
...options,
|
|
683
|
+
strict: true,
|
|
684
|
+
additionalProperties: false,
|
|
685
|
+
};
|
|
686
|
+
return new InterfaceSchema.InterfaceSchema(definition, strictOptions);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Create a passthrough version of a schema that preserves additional properties
|
|
690
|
+
*
|
|
691
|
+
* By default, ReliantType ignores extra properties in the input data (they're
|
|
692
|
+
* not included in the validated output). The `passthrough()` method changes this
|
|
693
|
+
* behavior to explicitly include all additional properties in the validated result,
|
|
694
|
+
* effectively making the schema more permissive.
|
|
695
|
+
*
|
|
696
|
+
* This is useful for proxy APIs, data transformation pipelines, or situations
|
|
697
|
+
* where you want to validate known fields while preserving unknown ones for
|
|
698
|
+
* later processing or forwarding to other systems.
|
|
699
|
+
*
|
|
700
|
+
* @param schema - The source schema to make passthrough
|
|
701
|
+
* @returns A new schema that includes additional properties in the output
|
|
702
|
+
*
|
|
703
|
+
* @example Basic passthrough behavior
|
|
704
|
+
* ```typescript
|
|
705
|
+
* const UserSchema = Interface({
|
|
706
|
+
* id: "number",
|
|
707
|
+
* name: "string",
|
|
708
|
+
* email: "email"
|
|
709
|
+
* });
|
|
710
|
+
*
|
|
711
|
+
* const PassthroughUserSchema = Mod.passthrough(UserSchema);
|
|
712
|
+
*
|
|
713
|
+
* const result = PassthroughUserSchema.parse({
|
|
714
|
+
* id: 1,
|
|
715
|
+
* name: "John",
|
|
716
|
+
* email: "john@example.com",
|
|
717
|
+
* age: 30, // Extra property
|
|
718
|
+
* department: "IT" // Extra property
|
|
719
|
+
* });
|
|
720
|
+
*
|
|
721
|
+
* console.log(result);
|
|
722
|
+
* // {
|
|
723
|
+
* // id: 1,
|
|
724
|
+
* // name: "John",
|
|
725
|
+
* // email: "john@example.com",
|
|
726
|
+
* // age: 30, // ✅ Preserved
|
|
727
|
+
* // department: "IT" // ✅ Preserved
|
|
728
|
+
* // }
|
|
729
|
+
* ```
|
|
730
|
+
*
|
|
731
|
+
* @example API proxy with validation
|
|
732
|
+
* ```typescript
|
|
733
|
+
* const KnownUserFieldsSchema = Interface({
|
|
734
|
+
* id: "number",
|
|
735
|
+
* name: "string",
|
|
736
|
+
* email: "email",
|
|
737
|
+
* role: "admin|user|moderator"
|
|
738
|
+
* });
|
|
739
|
+
*
|
|
740
|
+
* const ProxyUserSchema = Mod.passthrough(KnownUserFieldsSchema);
|
|
741
|
+
*
|
|
742
|
+
* // Validate known fields while preserving unknown ones
|
|
743
|
+
* app.post('/users/proxy', (req, res) => {
|
|
744
|
+
* const result = ProxyUserSchema.safeParse(req.body);
|
|
745
|
+
*
|
|
746
|
+
* if (!result.success) {
|
|
747
|
+
* return res.status(400).json({
|
|
748
|
+
* error: "Invalid known fields",
|
|
749
|
+
* details: result.errors
|
|
750
|
+
* });
|
|
751
|
+
* }
|
|
752
|
+
*
|
|
753
|
+
* // Forward to another service with all data preserved
|
|
754
|
+
* const response = await externalAPI.createUser(result.data);
|
|
755
|
+
* res.json(response);
|
|
756
|
+
* });
|
|
757
|
+
* ```
|
|
758
|
+
*
|
|
759
|
+
* @example Data transformation pipeline
|
|
760
|
+
* ```typescript
|
|
761
|
+
* const CoreDataSchema = Interface({
|
|
762
|
+
* timestamp: "date",
|
|
763
|
+
* userId: "number",
|
|
764
|
+
* action: "string"
|
|
765
|
+
* });
|
|
766
|
+
*
|
|
767
|
+
* const FlexibleDataSchema = Mod.passthrough(CoreDataSchema);
|
|
768
|
+
*
|
|
769
|
+
* // Process events with varying additional metadata
|
|
770
|
+
* function processEvent(rawEvent: unknown) {
|
|
771
|
+
* const result = FlexibleDataSchema.safeParse(rawEvent);
|
|
772
|
+
*
|
|
773
|
+
* if (!result.success) {
|
|
774
|
+
* throw new Error("Invalid core event structure");
|
|
775
|
+
* }
|
|
776
|
+
*
|
|
777
|
+
* const event = result.data;
|
|
778
|
+
*
|
|
779
|
+
* // Core fields are validated and typed
|
|
780
|
+
* console.log(`User ${event.userId} performed ${event.action} at ${event.timestamp}`);
|
|
781
|
+
*
|
|
782
|
+
* // Additional metadata is preserved for downstream processing
|
|
783
|
+
* if ('metadata' in event) {
|
|
784
|
+
* processMetadata(event.metadata);
|
|
785
|
+
* }
|
|
786
|
+
*
|
|
787
|
+
* return event; // All data preserved
|
|
788
|
+
* }
|
|
789
|
+
* ```
|
|
790
|
+
*
|
|
791
|
+
* @example Comparison with default and strict behavior
|
|
792
|
+
* ```typescript
|
|
793
|
+
* const Schema = Interface({ name: "string" });
|
|
794
|
+
* const PassthroughSchema = Mod.passthrough(Schema);
|
|
795
|
+
* const StrictSchema = Mod.strict(Schema);
|
|
796
|
+
*
|
|
797
|
+
* const input = { name: "John", extra: "data", more: "fields" };
|
|
798
|
+
*
|
|
799
|
+
* // Default: extra properties ignored
|
|
800
|
+
* const defaultResult = Schema.parse(input);
|
|
801
|
+
* console.log(defaultResult); // { name: "John" }
|
|
802
|
+
*
|
|
803
|
+
* // Passthrough: extra properties included
|
|
804
|
+
* const passthroughResult = PassthroughSchema.parse(input);
|
|
805
|
+
* console.log(passthroughResult); // { name: "John", extra: "data", more: "fields" }
|
|
806
|
+
*
|
|
807
|
+
* // Strict: extra properties cause error
|
|
808
|
+
* const strictResult = StrictSchema.safeParse(input);
|
|
809
|
+
* console.log(strictResult.success); // false
|
|
810
|
+
* ```
|
|
811
|
+
*/
|
|
812
|
+
static passthrough(schema) {
|
|
813
|
+
const definition = schema.definition;
|
|
814
|
+
const options = schema.options || {};
|
|
815
|
+
const passthroughOptions = {
|
|
816
|
+
...options,
|
|
817
|
+
strict: false,
|
|
818
|
+
additionalProperties: true,
|
|
819
|
+
};
|
|
820
|
+
return new InterfaceSchema.InterfaceSchema(definition, passthroughOptions);
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Create a schema that accepts null values for all fields
|
|
824
|
+
* @example
|
|
825
|
+
* ```typescript
|
|
826
|
+
* const UserSchema = Interface({ id: "number", name: "string" });
|
|
827
|
+
* const NullableSchema = Mod.nullable(UserSchema);
|
|
828
|
+
* // Result: { id: number | null, name: string | null }
|
|
829
|
+
* ```
|
|
830
|
+
*/
|
|
831
|
+
static nullable(schema) {
|
|
832
|
+
const definition = schema.definition;
|
|
833
|
+
const options = schema.options || {};
|
|
834
|
+
const nullableDefinition = {};
|
|
835
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
836
|
+
if (typeof value === "string") {
|
|
837
|
+
// Add null union to the type
|
|
838
|
+
nullableDefinition[key] = value.includes("|")
|
|
839
|
+
? `${value}|null`
|
|
840
|
+
: `${value}|null`;
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
nullableDefinition[key] = value;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
return new InterfaceSchema.InterfaceSchema(nullableDefinition, options);
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Get comprehensive metadata and statistics about a schema
|
|
850
|
+
*
|
|
851
|
+
* This method analyzes a schema and returns detailed information about its structure,
|
|
852
|
+
* including field counts, types, and other useful metadata. This is particularly
|
|
853
|
+
* useful for debugging, documentation generation, schema analysis tools, or
|
|
854
|
+
* building dynamic UIs based on schema structure.
|
|
855
|
+
*
|
|
856
|
+
* @param schema - The schema to analyze
|
|
857
|
+
* @returns Object containing detailed schema metadata
|
|
858
|
+
*
|
|
859
|
+
* @example Basic schema analysis
|
|
860
|
+
* ```typescript
|
|
861
|
+
* const UserSchema = Interface({
|
|
862
|
+
* id: "number",
|
|
863
|
+
* name: "string",
|
|
864
|
+
* email: "email?",
|
|
865
|
+
* profile: {
|
|
866
|
+
* bio: "string?",
|
|
867
|
+
* avatar: "string"
|
|
868
|
+
* },
|
|
869
|
+
* tags: "string[]?"
|
|
870
|
+
* });
|
|
871
|
+
*
|
|
872
|
+
* const info = Mod.info(UserSchema);
|
|
873
|
+
* console.log(info);
|
|
874
|
+
* // {
|
|
875
|
+
* // fieldCount: 5,
|
|
876
|
+
* // requiredFields: 3,
|
|
877
|
+
* // optionalFields: 2,
|
|
878
|
+
* // types: ["number", "string", "email?", "object", "string[]?"],
|
|
879
|
+
* // fields: ["id", "name", "email", "profile", "tags"]
|
|
880
|
+
* // }
|
|
881
|
+
* ```
|
|
882
|
+
*
|
|
883
|
+
* @example Using info for documentation generation
|
|
884
|
+
* ```typescript
|
|
885
|
+
* function generateSchemaDoc(schema: InterfaceSchema<any>, name: string) {
|
|
886
|
+
* const info = Mod.info(schema);
|
|
887
|
+
*
|
|
888
|
+
* return `
|
|
889
|
+
* ## ${name} Schema
|
|
890
|
+
*
|
|
891
|
+
* **Fields:** ${info.fieldCount} total (${info.requiredFields} required, ${info.optionalFields} optional)
|
|
892
|
+
*
|
|
893
|
+
* **Field Types:**
|
|
894
|
+
* ${info.fields.map((field, i) => `- ${field}: ${info.types[i]}`).join('\n')}
|
|
895
|
+
* `;
|
|
896
|
+
* }
|
|
897
|
+
*
|
|
898
|
+
* const doc = generateSchemaDoc(UserSchema, "User");
|
|
899
|
+
* console.log(doc);
|
|
900
|
+
* ```
|
|
901
|
+
*
|
|
902
|
+
* @example Schema complexity analysis
|
|
903
|
+
* ```typescript
|
|
904
|
+
* function analyzeSchemaComplexity(schema: InterfaceSchema<any>) {
|
|
905
|
+
* const info = Mod.info(schema);
|
|
906
|
+
*
|
|
907
|
+
* const complexity = {
|
|
908
|
+
* simple: info.fieldCount <= 5,
|
|
909
|
+
* hasOptionalFields: info.optionalFields > 0,
|
|
910
|
+
* hasArrays: info.types.some(type => type.includes('[]')),
|
|
911
|
+
* hasNestedObjects: info.types.includes('object'),
|
|
912
|
+
* typeVariety: new Set(info.types.map(type =>
|
|
913
|
+
* type.replace(/\?|\[\]/g, '')
|
|
914
|
+
* )).size
|
|
915
|
+
* };
|
|
916
|
+
*
|
|
917
|
+
* return complexity;
|
|
918
|
+
* }
|
|
919
|
+
*
|
|
920
|
+
* const complexity = analyzeSchemaComplexity(UserSchema);
|
|
921
|
+
* console.log(complexity);
|
|
922
|
+
* // {
|
|
923
|
+
* // simple: false,
|
|
924
|
+
* // hasOptionalFields: true,
|
|
925
|
+
* // hasArrays: true,
|
|
926
|
+
* // hasNestedObjects: true,
|
|
927
|
+
* // typeVariety: 4
|
|
928
|
+
* // }
|
|
929
|
+
* ```
|
|
930
|
+
*
|
|
931
|
+
* @example Dynamic form generation
|
|
932
|
+
* ```typescript
|
|
933
|
+
* function generateFormFields(schema: InterfaceSchema<any>) {
|
|
934
|
+
* const info = Mod.info(schema);
|
|
935
|
+
*
|
|
936
|
+
* return info.fields.map((fieldName, index) => {
|
|
937
|
+
* const fieldType = info.types[index];
|
|
938
|
+
* const isRequired = !fieldType.includes('?');
|
|
939
|
+
* const baseType = fieldType.replace(/\?|\[\]/g, '');
|
|
940
|
+
*
|
|
941
|
+
* return {
|
|
942
|
+
* name: fieldName,
|
|
943
|
+
* type: baseType,
|
|
944
|
+
* required: isRequired,
|
|
945
|
+
* isArray: fieldType.includes('[]'),
|
|
946
|
+
* inputType: getInputType(baseType) // Custom function
|
|
947
|
+
* };
|
|
948
|
+
* });
|
|
949
|
+
* }
|
|
950
|
+
*
|
|
951
|
+
* function getInputType(type: string): string {
|
|
952
|
+
* switch (type) {
|
|
953
|
+
* case 'string': return 'text';
|
|
954
|
+
* case 'number': return 'number';
|
|
955
|
+
* case 'email': return 'email';
|
|
956
|
+
* case 'date': return 'date';
|
|
957
|
+
* case 'boolean': return 'checkbox';
|
|
958
|
+
* default: return 'text';
|
|
959
|
+
* }
|
|
960
|
+
* }
|
|
961
|
+
*
|
|
962
|
+
* const formFields = generateFormFields(UserSchema);
|
|
963
|
+
* ```
|
|
964
|
+
*
|
|
965
|
+
* @example Schema validation and testing
|
|
966
|
+
* ```typescript
|
|
967
|
+
* function validateSchemaStructure(schema: InterfaceSchema<any>) {
|
|
968
|
+
* const info = Mod.info(schema);
|
|
969
|
+
* const issues: string[] = [];
|
|
970
|
+
*
|
|
971
|
+
* if (info.fieldCount === 0) {
|
|
972
|
+
* issues.push("Schema has no fields");
|
|
973
|
+
* }
|
|
974
|
+
*
|
|
975
|
+
* if (info.requiredFields === 0) {
|
|
976
|
+
* issues.push("Schema has no required fields");
|
|
977
|
+
* }
|
|
978
|
+
*
|
|
979
|
+
* if (info.fieldCount > 20) {
|
|
980
|
+
* issues.push("Schema might be too complex (>20 fields)");
|
|
981
|
+
* }
|
|
982
|
+
*
|
|
983
|
+
* const unknownTypes = info.types.filter(type =>
|
|
984
|
+
* !['string', 'number', 'boolean', 'date', 'email', 'object'].some(known =>
|
|
985
|
+
* type.replace(/\?|\[\]/g, '').includes(known)
|
|
986
|
+
* )
|
|
987
|
+
* );
|
|
988
|
+
*
|
|
989
|
+
* if (unknownTypes.length > 0) {
|
|
990
|
+
* issues.push(`Unknown types found: ${unknownTypes.join(', ')}`);
|
|
991
|
+
* }
|
|
992
|
+
*
|
|
993
|
+
* return {
|
|
994
|
+
* valid: issues.length === 0,
|
|
995
|
+
* issues,
|
|
996
|
+
* info
|
|
997
|
+
* };
|
|
998
|
+
* }
|
|
999
|
+
* ```
|
|
1000
|
+
*/
|
|
1001
|
+
static info(schema) {
|
|
1002
|
+
const definition = schema.definition;
|
|
1003
|
+
const fields = Object.keys(definition);
|
|
1004
|
+
const types = Object.values(definition).map((v) => typeof v === "string" ? v : "object");
|
|
1005
|
+
const optionalFields = types.filter((type) => typeof type === "string" && type.endsWith("?")).length;
|
|
1006
|
+
const requiredFields = fields.length - optionalFields;
|
|
1007
|
+
return {
|
|
1008
|
+
fieldCount: fields.length,
|
|
1009
|
+
requiredFields,
|
|
1010
|
+
optionalFields,
|
|
1011
|
+
types,
|
|
1012
|
+
fields,
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Clone a schema with optional modifications
|
|
1017
|
+
* @example
|
|
1018
|
+
* ```typescript
|
|
1019
|
+
* const UserSchema = Interface({ id: "number", name: "string" });
|
|
1020
|
+
* const ClonedSchema = Mod.clone(UserSchema, { preserveOptions: true });
|
|
1021
|
+
* ```
|
|
1022
|
+
*/
|
|
1023
|
+
static clone(schema, options = {}) {
|
|
1024
|
+
const definition = schema.definition;
|
|
1025
|
+
const schemaOptions = options.preserveOptions
|
|
1026
|
+
? schema.options || {}
|
|
1027
|
+
: {};
|
|
1028
|
+
return new InterfaceSchema.InterfaceSchema(JSON.parse(JSON.stringify(definition)), schemaOptions);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
exports.Mod = Mod;
|
|
1033
|
+
//# sourceMappingURL=Mod.js.map
|