@maroonedog/luq 0.1.0-alpha
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 +9 -0
- package/README.md +879 -0
- package/dist/constants.d.ts +27 -0
- package/dist/core/async.experimental/async-context.d.ts +60 -0
- package/dist/core/builder/array-batch-optimizer.d.ts +66 -0
- package/dist/core/builder/context/field-context.d.ts +31 -0
- package/dist/core/builder/context/field-type-detector.d.ts +19 -0
- package/dist/core/builder/core/builder.d.ts +10 -0
- package/dist/core/builder/core/field-builder.d.ts +13 -0
- package/dist/core/builder/core/index.d.ts +17 -0
- package/dist/core/builder/index.d.ts +24 -0
- package/dist/core/builder/nested-array-processor.d.ts +52 -0
- package/dist/core/builder/plugins/composable-conditional-plugin.d.ts +32 -0
- package/dist/core/builder/plugins/composable-directly-plugin.d.ts +32 -0
- package/dist/core/builder/plugins/composable-plugin.d.ts +242 -0
- package/dist/core/builder/plugins/plugin-creator.d.ts +38 -0
- package/dist/core/builder/plugins/plugin-interfaces.d.ts +343 -0
- package/dist/core/builder/plugins/plugin-types.d.ts +441 -0
- package/dist/core/builder/raw-validator.d.ts +22 -0
- package/dist/core/builder/types/field-options.d.ts +46 -0
- package/dist/core/builder/types/types.d.ts +318 -0
- package/dist/core/builder/ultra-fast-validator.d.ts +30 -0
- package/dist/core/builder/validator-factory.d.ts +29 -0
- package/dist/core/global-config.d.ts +27 -0
- package/dist/core/index.d.ts +36 -0
- package/dist/core/optimization/array-batch-validator.d.ts +68 -0
- package/dist/core/optimization/core/field-utils.d.ts +103 -0
- package/dist/core/optimization/core/strategy-factory.d.ts +84 -0
- package/dist/core/optimization/core/validation-engine.d.ts +107 -0
- package/dist/core/optimization/execution-strategy-selector.d.ts +23 -0
- package/dist/core/optimization/unified-validator.d.ts +45 -0
- package/dist/core/plugin/__tests__/test-utils.d.ts +1 -0
- package/dist/core/plugin/arrayContains.d.ts +37 -0
- package/dist/core/plugin/arrayIncludes.d.ts +42 -0
- package/dist/core/plugin/arrayMaxLength.d.ts +43 -0
- package/dist/core/plugin/arrayMinLength.d.ts +43 -0
- package/dist/core/plugin/arrayUnique.d.ts +41 -0
- package/dist/core/plugin/booleanFalsy.d.ts +41 -0
- package/dist/core/plugin/booleanTruthy.d.ts +38 -0
- package/dist/core/plugin/compareField.d.ts +58 -0
- package/dist/core/plugin/conditionalSchema.d.ts +24 -0
- package/dist/core/plugin/custom.d.ts +60 -0
- package/dist/core/plugin/fromContext.d.ts +150 -0
- package/dist/core/plugin/index.d.ts +71 -0
- package/dist/core/plugin/jsonSchema/dsl-converter.d.ts +22 -0
- package/dist/core/plugin/jsonSchema/error-generation.d.ts +14 -0
- package/dist/core/plugin/jsonSchema/format-validators.d.ts +20 -0
- package/dist/core/plugin/jsonSchema/index.d.ts +11 -0
- package/dist/core/plugin/jsonSchema/plugin.d.ts +35 -0
- package/dist/core/plugin/jsonSchema/ref-resolver.d.ts +14 -0
- package/dist/core/plugin/jsonSchema/types.d.ts +69 -0
- package/dist/core/plugin/jsonSchema/validation-core.d.ts +29 -0
- package/dist/core/plugin/jsonSchemaFullFeature.d.ts +31 -0
- package/dist/core/plugin/literal.d.ts +40 -0
- package/dist/core/plugin/message-factories.d.ts +9 -0
- package/dist/core/plugin/nullable.d.ts +34 -0
- package/dist/core/plugin/numberFinite.d.ts +41 -0
- package/dist/core/plugin/numberInteger.d.ts +41 -0
- package/dist/core/plugin/numberMax.d.ts +49 -0
- package/dist/core/plugin/numberMin.d.ts +49 -0
- package/dist/core/plugin/numberMultipleOf.d.ts +42 -0
- package/dist/core/plugin/numberNegative.d.ts +41 -0
- package/dist/core/plugin/numberPositive.d.ts +41 -0
- package/dist/core/plugin/numberRange.d.ts +48 -0
- package/dist/core/plugin/object.d.ts +43 -0
- package/dist/core/plugin/objectAdditionalProperties.d.ts +51 -0
- package/dist/core/plugin/objectDependentRequired.d.ts +42 -0
- package/dist/core/plugin/objectDependentSchemas.d.ts +40 -0
- package/dist/core/plugin/objectMaxProperties.d.ts +42 -0
- package/dist/core/plugin/objectMinProperties.d.ts +42 -0
- package/dist/core/plugin/objectPatternProperties.d.ts +46 -0
- package/dist/core/plugin/objectPropertyNames.d.ts +36 -0
- package/dist/core/plugin/objectRecursively.d.ts +81 -0
- package/dist/core/plugin/oneOf.d.ts +44 -0
- package/dist/core/plugin/optional.d.ts +35 -0
- package/dist/core/plugin/optionalIf.d.ts +42 -0
- package/dist/core/plugin/orFail.d.ts +132 -0
- package/dist/core/plugin/readOnlyWriteOnly.d.ts +48 -0
- package/dist/core/plugin/required.d.ts +45 -0
- package/dist/core/plugin/requiredIf.d.ts +66 -0
- package/dist/core/plugin/shared-constants.d.ts +45 -0
- package/dist/core/plugin/shared.d.ts +3 -0
- package/dist/core/plugin/skip.d.ts +57 -0
- package/dist/core/plugin/stitch-typed.d.ts +15 -0
- package/dist/core/plugin/stitch.d.ts +1 -0
- package/dist/core/plugin/stitchSimple.d.ts +4 -0
- package/dist/core/plugin/stringAlphanumeric.d.ts +42 -0
- package/dist/core/plugin/stringBase64.d.ts +119 -0
- package/dist/core/plugin/stringContentEncoding.d.ts +43 -0
- package/dist/core/plugin/stringContentMediaType.d.ts +47 -0
- package/dist/core/plugin/stringDate.d.ts +48 -0
- package/dist/core/plugin/stringDatetime.d.ts +108 -0
- package/dist/core/plugin/stringDuration.d.ts +41 -0
- package/dist/core/plugin/stringEmail.d.ts +81 -0
- package/dist/core/plugin/stringEndsWith.d.ts +42 -0
- package/dist/core/plugin/stringExactLength.d.ts +46 -0
- package/dist/core/plugin/stringHostname.d.ts +104 -0
- package/dist/core/plugin/stringIpv4.d.ts +85 -0
- package/dist/core/plugin/stringIpv6.d.ts +104 -0
- package/dist/core/plugin/stringIri.d.ts +117 -0
- package/dist/core/plugin/stringIriReference.d.ts +43 -0
- package/dist/core/plugin/stringJsonPointer.d.ts +107 -0
- package/dist/core/plugin/stringMax.d.ts +43 -0
- package/dist/core/plugin/stringMin.d.ts +43 -0
- package/dist/core/plugin/stringPattern.d.ts +40 -0
- package/dist/core/plugin/stringRelativeJsonPointer.d.ts +42 -0
- package/dist/core/plugin/stringStartsWith.d.ts +42 -0
- package/dist/core/plugin/stringTime.d.ts +39 -0
- package/dist/core/plugin/stringUriTemplate.d.ts +43 -0
- package/dist/core/plugin/stringUrl.d.ts +97 -0
- package/dist/core/plugin/testUtils.d.ts +15 -0
- package/dist/core/plugin/transform-type-restrictions.d.ts +61 -0
- package/dist/core/plugin/transform.d.ts +35 -0
- package/dist/core/plugin/tupleBuilder.d.ts +66 -0
- package/dist/core/plugin/types.d.ts +143 -0
- package/dist/core/plugin/unionGuard.d.ts +50 -0
- package/dist/core/plugin/utils/field-accessor-optimized.d.ts +50 -0
- package/dist/core/plugin/utils/field-accessor.d.ts +107 -0
- package/dist/core/plugin/uuid.d.ts +95 -0
- package/dist/core/plugin/validateIf.d.ts +57 -0
- package/dist/core/registry/plugin-registry.d.ts +116 -0
- package/dist/core/registry.d.ts +6 -0
- package/dist/core/transform/index.d.ts +1 -0
- package/dist/core/transform/string/defaultValue.d.ts +6 -0
- package/dist/core/transform/string/index.d.ts +3 -0
- package/dist/core/transform/string/replace.d.ts +14 -0
- package/dist/core/transform/string/sanitize.d.ts +6 -0
- package/dist/core/utils/type-guards.d.ts +68 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +7 -0
- package/dist/plugins/arrayContains.d.ts +37 -0
- package/dist/plugins/arrayContains.js +1 -0
- package/dist/plugins/arrayContains.mjs +1 -0
- package/dist/plugins/arrayIncludes.d.ts +42 -0
- package/dist/plugins/arrayIncludes.js +1 -0
- package/dist/plugins/arrayIncludes.mjs +1 -0
- package/dist/plugins/arrayMaxLength.d.ts +43 -0
- package/dist/plugins/arrayMaxLength.js +1 -0
- package/dist/plugins/arrayMaxLength.mjs +1 -0
- package/dist/plugins/arrayMinLength.d.ts +43 -0
- package/dist/plugins/arrayMinLength.js +1 -0
- package/dist/plugins/arrayMinLength.mjs +1 -0
- package/dist/plugins/arrayUnique.d.ts +41 -0
- package/dist/plugins/arrayUnique.js +1 -0
- package/dist/plugins/arrayUnique.mjs +1 -0
- package/dist/plugins/booleanFalsy.d.ts +41 -0
- package/dist/plugins/booleanFalsy.js +1 -0
- package/dist/plugins/booleanFalsy.mjs +1 -0
- package/dist/plugins/booleanTruthy.d.ts +38 -0
- package/dist/plugins/booleanTruthy.js +1 -0
- package/dist/plugins/booleanTruthy.mjs +1 -0
- package/dist/plugins/compareField.d.ts +58 -0
- package/dist/plugins/compareField.js +1 -0
- package/dist/plugins/compareField.mjs +1 -0
- package/dist/plugins/custom.d.ts +60 -0
- package/dist/plugins/custom.js +1 -0
- package/dist/plugins/custom.mjs +1 -0
- package/dist/plugins/jsonSchema.d.ts +11 -0
- package/dist/plugins/jsonSchema.js +1 -0
- package/dist/plugins/jsonSchema.mjs +1 -0
- package/dist/plugins/jsonSchemaFullFeature.d.ts +31 -0
- package/dist/plugins/jsonSchemaFullFeature.js +1 -0
- package/dist/plugins/jsonSchemaFullFeature.mjs +1 -0
- package/dist/plugins/literal.d.ts +40 -0
- package/dist/plugins/literal.js +1 -0
- package/dist/plugins/literal.mjs +1 -0
- package/dist/plugins/nullable.d.ts +34 -0
- package/dist/plugins/nullable.js +1 -0
- package/dist/plugins/nullable.mjs +1 -0
- package/dist/plugins/numberInteger.d.ts +41 -0
- package/dist/plugins/numberInteger.js +1 -0
- package/dist/plugins/numberInteger.mjs +1 -0
- package/dist/plugins/numberMax.d.ts +49 -0
- package/dist/plugins/numberMax.js +1 -0
- package/dist/plugins/numberMax.mjs +1 -0
- package/dist/plugins/numberMin.d.ts +49 -0
- package/dist/plugins/numberMin.js +1 -0
- package/dist/plugins/numberMin.mjs +1 -0
- package/dist/plugins/numberMultipleOf.d.ts +42 -0
- package/dist/plugins/numberMultipleOf.js +1 -0
- package/dist/plugins/numberMultipleOf.mjs +1 -0
- package/dist/plugins/numberNegative.d.ts +41 -0
- package/dist/plugins/numberNegative.js +1 -0
- package/dist/plugins/numberNegative.mjs +1 -0
- package/dist/plugins/numberPositive.d.ts +41 -0
- package/dist/plugins/numberPositive.js +1 -0
- package/dist/plugins/numberPositive.mjs +1 -0
- package/dist/plugins/object.d.ts +43 -0
- package/dist/plugins/object.js +1 -0
- package/dist/plugins/object.mjs +1 -0
- package/dist/plugins/objectAdditionalProperties.d.ts +51 -0
- package/dist/plugins/objectAdditionalProperties.js +1 -0
- package/dist/plugins/objectAdditionalProperties.mjs +1 -0
- package/dist/plugins/objectDependentRequired.d.ts +42 -0
- package/dist/plugins/objectDependentRequired.js +1 -0
- package/dist/plugins/objectDependentRequired.mjs +1 -0
- package/dist/plugins/objectDependentSchemas.d.ts +40 -0
- package/dist/plugins/objectDependentSchemas.js +1 -0
- package/dist/plugins/objectDependentSchemas.mjs +1 -0
- package/dist/plugins/objectMaxProperties.d.ts +42 -0
- package/dist/plugins/objectMaxProperties.js +1 -0
- package/dist/plugins/objectMaxProperties.mjs +1 -0
- package/dist/plugins/objectMinProperties.d.ts +42 -0
- package/dist/plugins/objectMinProperties.js +1 -0
- package/dist/plugins/objectMinProperties.mjs +1 -0
- package/dist/plugins/objectPatternProperties.d.ts +46 -0
- package/dist/plugins/objectPatternProperties.js +1 -0
- package/dist/plugins/objectPatternProperties.mjs +1 -0
- package/dist/plugins/objectPropertyNames.d.ts +36 -0
- package/dist/plugins/objectPropertyNames.js +1 -0
- package/dist/plugins/objectPropertyNames.mjs +1 -0
- package/dist/plugins/oneOf.d.ts +44 -0
- package/dist/plugins/oneOf.js +1 -0
- package/dist/plugins/oneOf.mjs +1 -0
- package/dist/plugins/optional.d.ts +35 -0
- package/dist/plugins/optional.js +1 -0
- package/dist/plugins/optional.mjs +1 -0
- package/dist/plugins/readOnlyWriteOnly.d.ts +48 -0
- package/dist/plugins/readOnlyWriteOnly.js +1 -0
- package/dist/plugins/readOnlyWriteOnly.mjs +1 -0
- package/dist/plugins/required.d.ts +45 -0
- package/dist/plugins/required.js +1 -0
- package/dist/plugins/required.mjs +1 -0
- package/dist/plugins/requiredIf.d.ts +66 -0
- package/dist/plugins/requiredIf.js +1 -0
- package/dist/plugins/requiredIf.mjs +1 -0
- package/dist/plugins/skip.d.ts +57 -0
- package/dist/plugins/skip.js +1 -0
- package/dist/plugins/skip.mjs +1 -0
- package/dist/plugins/stringBase64.d.ts +119 -0
- package/dist/plugins/stringBase64.js +1 -0
- package/dist/plugins/stringBase64.mjs +1 -0
- package/dist/plugins/stringContentEncoding.d.ts +43 -0
- package/dist/plugins/stringContentEncoding.js +1 -0
- package/dist/plugins/stringContentEncoding.mjs +1 -0
- package/dist/plugins/stringContentMediaType.d.ts +47 -0
- package/dist/plugins/stringContentMediaType.js +1 -0
- package/dist/plugins/stringContentMediaType.mjs +1 -0
- package/dist/plugins/stringDate.d.ts +48 -0
- package/dist/plugins/stringDate.js +1 -0
- package/dist/plugins/stringDate.mjs +1 -0
- package/dist/plugins/stringDatetime.d.ts +108 -0
- package/dist/plugins/stringDatetime.js +1 -0
- package/dist/plugins/stringDatetime.mjs +1 -0
- package/dist/plugins/stringDuration.d.ts +41 -0
- package/dist/plugins/stringDuration.js +1 -0
- package/dist/plugins/stringDuration.mjs +1 -0
- package/dist/plugins/stringEmail.d.ts +81 -0
- package/dist/plugins/stringEmail.js +1 -0
- package/dist/plugins/stringEmail.mjs +1 -0
- package/dist/plugins/stringHostname.d.ts +104 -0
- package/dist/plugins/stringHostname.js +1 -0
- package/dist/plugins/stringHostname.mjs +1 -0
- package/dist/plugins/stringIpv4.d.ts +85 -0
- package/dist/plugins/stringIpv4.js +1 -0
- package/dist/plugins/stringIpv4.mjs +1 -0
- package/dist/plugins/stringIpv6.d.ts +104 -0
- package/dist/plugins/stringIpv6.js +1 -0
- package/dist/plugins/stringIpv6.mjs +1 -0
- package/dist/plugins/stringIri.d.ts +117 -0
- package/dist/plugins/stringIri.js +1 -0
- package/dist/plugins/stringIri.mjs +1 -0
- package/dist/plugins/stringIriReference.d.ts +43 -0
- package/dist/plugins/stringIriReference.js +1 -0
- package/dist/plugins/stringIriReference.mjs +1 -0
- package/dist/plugins/stringJsonPointer.d.ts +107 -0
- package/dist/plugins/stringJsonPointer.js +1 -0
- package/dist/plugins/stringJsonPointer.mjs +1 -0
- package/dist/plugins/stringMax.d.ts +43 -0
- package/dist/plugins/stringMax.js +1 -0
- package/dist/plugins/stringMax.mjs +1 -0
- package/dist/plugins/stringMin.d.ts +43 -0
- package/dist/plugins/stringMin.js +1 -0
- package/dist/plugins/stringMin.mjs +1 -0
- package/dist/plugins/stringPattern.d.ts +40 -0
- package/dist/plugins/stringPattern.js +1 -0
- package/dist/plugins/stringPattern.mjs +1 -0
- package/dist/plugins/stringRelativeJsonPointer.d.ts +42 -0
- package/dist/plugins/stringRelativeJsonPointer.js +1 -0
- package/dist/plugins/stringRelativeJsonPointer.mjs +1 -0
- package/dist/plugins/stringTime.d.ts +39 -0
- package/dist/plugins/stringTime.js +1 -0
- package/dist/plugins/stringTime.mjs +1 -0
- package/dist/plugins/stringUriTemplate.d.ts +43 -0
- package/dist/plugins/stringUriTemplate.js +1 -0
- package/dist/plugins/stringUriTemplate.mjs +1 -0
- package/dist/plugins/stringUrl.d.ts +97 -0
- package/dist/plugins/stringUrl.js +1 -0
- package/dist/plugins/stringUrl.mjs +1 -0
- package/dist/plugins/transform.d.ts +35 -0
- package/dist/plugins/transform.js +1 -0
- package/dist/plugins/transform.mjs +1 -0
- package/dist/plugins/tupleBuilder.d.ts +66 -0
- package/dist/plugins/tupleBuilder.js +1 -0
- package/dist/plugins/tupleBuilder.mjs +1 -0
- package/dist/plugins/uuid.d.ts +95 -0
- package/dist/plugins/uuid.js +1 -0
- package/dist/plugins/uuid.mjs +1 -0
- package/dist/plugins/validateIf.d.ts +57 -0
- package/dist/plugins/validateIf.js +1 -0
- package/dist/plugins/validateIf.mjs +1 -0
- package/dist/types/array-type-analysis.d.ts +115 -0
- package/dist/types/index.d.ts +74 -0
- package/dist/types/indexed-result.d.ts +44 -0
- package/dist/types/result.d.ts +159 -0
- package/dist/types/stitch-types.d.ts +118 -0
- package/dist/types/util.d.ts +19 -0
- package/dist/types/valitator.d.ts +10 -0
- package/package.json +353 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ValidationOptions, MessageContext } from "../core/plugin/types";
|
|
2
|
+
export interface ValidateIfContext extends MessageContext {
|
|
3
|
+
condition?: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* @luq-plugin
|
|
7
|
+
* @name validateIf
|
|
8
|
+
* @category conditional
|
|
9
|
+
* @description Conditionally applies all validation rules to a field based on a dynamic condition, with support for array context validation
|
|
10
|
+
* @allowedTypes ["string", "number", "boolean", "array", "object", "date", "union"]
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // Validate URL only when custom endpoint is enabled
|
|
14
|
+
* const validator = Builder()
|
|
15
|
+
* .use(validateIfPlugin)
|
|
16
|
+
* .for<ConfigData>()
|
|
17
|
+
* .v("customEndpoint", b =>
|
|
18
|
+
* b.string
|
|
19
|
+
* .validateIf(values => values.useCustomEndpoint)
|
|
20
|
+
* .url()
|
|
21
|
+
* .min(10)
|
|
22
|
+
* )
|
|
23
|
+
* .build();
|
|
24
|
+
*
|
|
25
|
+
* // Skip validation in local environment
|
|
26
|
+
* builder.v("apiKey", b =>
|
|
27
|
+
* b.string
|
|
28
|
+
* .validateIf(values => values.environment !== 'local')
|
|
29
|
+
* .required()
|
|
30
|
+
* .min(32)
|
|
31
|
+
* )
|
|
32
|
+
*
|
|
33
|
+
* // Conditional sections in forms
|
|
34
|
+
* builder.v("businessDetails.taxId", b =>
|
|
35
|
+
* b.string
|
|
36
|
+
* .validateIf(values => values.accountType === 'business')
|
|
37
|
+
* .required()
|
|
38
|
+
* .pattern(/^\d{9}$/)
|
|
39
|
+
* )
|
|
40
|
+
* ```
|
|
41
|
+
* @params
|
|
42
|
+
* - condition: (allValues: TObject, arrayContext?: ArrayContext) => boolean - Function that returns true if validation should run, with access to array context
|
|
43
|
+
* - options?: ValidationOptions - Optional configuration
|
|
44
|
+
* @returns Validation function that skips all validations when condition is false
|
|
45
|
+
* @customError
|
|
46
|
+
* ```typescript
|
|
47
|
+
* This plugin does not generate errors - it controls whether validation runs
|
|
48
|
+
* ```
|
|
49
|
+
* @since 0.1.0-alpha
|
|
50
|
+
*/
|
|
51
|
+
export declare const validateIfPlugin: import("../index").TypedPlugin<"validateIf", "validateIf", <TObject>(condition: (allValues: TObject, arrayContext?: import("./types").ArrayContext) => boolean, options?: ValidationOptions<ValidateIfContext>) => {
|
|
52
|
+
check: (value: any, allValues?: TObject, arrayContext?: import("./types").ArrayContext) => boolean;
|
|
53
|
+
code: string;
|
|
54
|
+
getErrorMessage: () => never;
|
|
55
|
+
params: (((allValues: TObject, arrayContext?: import("./types").ArrayContext) => boolean) | ValidationOptions<ValidateIfContext>)[];
|
|
56
|
+
shouldSkipAllValidation: (value: any, allValues?: TObject, arrayContext?: import("./types").ArrayContext) => boolean;
|
|
57
|
+
}, readonly ["string", "number", "boolean", "array", "object", "date", "union"], "validator", "conditional">;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var m=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var g=(e,n)=>{for(var r in n)m(e,r,{get:n[r],enumerable:!0})},y=(e,n,r,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of T(n))!d.call(e,t)&&t!==r&&m(e,t,{get:()=>n[t],enumerable:!(a=p(n,t))||a.enumerable});return e};var c=e=>y(m({},"__esModule",{value:!0}),e);var h={};g(h,{validateIfPlugin:()=>N});module.exports=c(h);var f=(e,n,r,a)=>{let o=(i=>(...l)=>{let s=i(...l);return s&&typeof s=="object"&&"check"in s?{...s,pluginName:a}:s})(r);switch(e){case"conditional":return(i,...l)=>o(i,...l);case"fieldReference":return(i,...l)=>o(i,...l);case"multiFieldReference":return o;case"transform":return i=>o(i);case"arrayElement":return(i,...l)=>o(i,...l);case"context":return i=>o(i);default:return o}};function u(e){let{name:n,methodName:r,allowedTypes:a,category:t,impl:o}=e;return{name:n,methodName:r,allowedTypes:a,category:t,create:()=>f(t,r,o,n)}}var w=Object.freeze({valid:!0,__skipAllValidation:!0}),x=["string","number","boolean","array","object","date","union"],N=u({name:"validateIf",methodName:"validateIf",allowedTypes:x,category:"conditional",impl:(e,n)=>({check:(r,a,t)=>(!a||!e(a,t),!0),code:"validateIf",getErrorMessage:()=>{throw new Error("validateIf plugin should never generate errors")},params:[e,n],shouldSkipAllValidation:(r,a,t)=>a?!e(a,t):!1})});0&&(module.exports={validateIfPlugin});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var u=(a,l,i,t)=>{let e=(n=>(...o)=>{let s=n(...o);return s&&typeof s=="object"&&"check"in s?{...s,pluginName:t}:s})(i);switch(a){case"conditional":return(n,...o)=>e(n,...o);case"fieldReference":return(n,...o)=>e(n,...o);case"multiFieldReference":return e;case"transform":return n=>e(n);case"arrayElement":return(n,...o)=>e(n,...o);case"context":return n=>e(n);default:return e}};function m(a){let{name:l,methodName:i,allowedTypes:t,category:r,impl:e}=a;return{name:l,methodName:i,allowedTypes:t,category:r,create:()=>u(r,i,e,l)}}var g=Object.freeze({valid:!0,__skipAllValidation:!0}),p=["string","number","boolean","array","object","date","union"],y=m({name:"validateIf",methodName:"validateIf",allowedTypes:p,category:"conditional",impl:(a,l)=>({check:(i,t,r)=>(!t||!a(t,r),!0),code:"validateIf",getErrorMessage:()=>{throw new Error("validateIf plugin should never generate errors")},params:[a,l],shouldSkipAllValidation:(i,t,r)=>t?!a(t,r):!1})});export{y as validateIfPlugin};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time TypeScript type analysis for multi-dimensional arrays
|
|
3
|
+
* Enables Array<Array<Array>> pattern optimization through compile-time type inspection
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Extract array depth from a type at compile time
|
|
7
|
+
* Array<string> → 1
|
|
8
|
+
* Array<Array<string>> → 2
|
|
9
|
+
* Array<Array<Array<string>>> → 3
|
|
10
|
+
*
|
|
11
|
+
* Note: TypeScript's type system has limitations with recursive arithmetic,
|
|
12
|
+
* so we use a more practical approach with explicit depth levels
|
|
13
|
+
*/
|
|
14
|
+
export type ArrayDepth<T> = T extends readonly (infer U)[] ? U extends readonly (infer V)[] ? V extends readonly (infer W)[] ? W extends readonly (infer X)[] ? X extends readonly (infer Y)[] ? 5 : 4 : 3 : 2 : 1 : 0;
|
|
15
|
+
/**
|
|
16
|
+
* Extract the final element type from nested arrays
|
|
17
|
+
* Array<Array<{name: string}>> → {name: string}
|
|
18
|
+
*/
|
|
19
|
+
export type ArrayElementType<T> = T extends readonly (infer U)[] ? ArrayElementType<U> : T;
|
|
20
|
+
/**
|
|
21
|
+
* Generate path pattern for nested array access
|
|
22
|
+
* Depth 1 → "[i]"
|
|
23
|
+
* Depth 2 → "[i][j]"
|
|
24
|
+
* Depth 3 → "[i][j][k]"
|
|
25
|
+
*/
|
|
26
|
+
export type ArrayIndexPattern<Depth extends number> = Depth extends 1 ? "[i]" : Depth extends 2 ? "[i][j]" : Depth extends 3 ? "[i][j][k]" : Depth extends 4 ? "[i][j][k][l]" : Depth extends 5 ? "[i][j][k][l][m]" : string;
|
|
27
|
+
/**
|
|
28
|
+
* Array structure information resolved at build time
|
|
29
|
+
*/
|
|
30
|
+
export interface ArrayStructureInfo<T = any> {
|
|
31
|
+
readonly depth: number;
|
|
32
|
+
readonly elementType: T;
|
|
33
|
+
readonly indexPattern: string;
|
|
34
|
+
readonly loopVariables: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve array structure at compile time
|
|
38
|
+
*/
|
|
39
|
+
export type ResolveArrayStructure<T> = {
|
|
40
|
+
readonly depth: ArrayDepth<T>;
|
|
41
|
+
readonly elementType: ArrayElementType<T>;
|
|
42
|
+
readonly indexPattern: ArrayIndexPattern<ArrayDepth<T>>;
|
|
43
|
+
readonly loopVariables: ArrayDepth<T> extends 1 ? readonly ["i"] : ArrayDepth<T> extends 2 ? readonly ["i", "j"] : ArrayDepth<T> extends 3 ? readonly ["i", "j", "k"] : ArrayDepth<T> extends 4 ? readonly ["i", "j", "k", "l"] : ArrayDepth<T> extends 5 ? readonly ["i", "j", "k", "l", "m"] : readonly string[];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Build-time array structure analyzer
|
|
47
|
+
* Creates optimized validation functions based on TypeScript type information
|
|
48
|
+
*/
|
|
49
|
+
export declare class BuildTimeArrayAnalyzer {
|
|
50
|
+
/**
|
|
51
|
+
* Analyze array structure from TypeScript type at build time
|
|
52
|
+
* This is called during field builder analysis phase
|
|
53
|
+
*/
|
|
54
|
+
static analyzeArrayStructure<T>(fieldPath: string, sampleValue?: T): ArrayStructureInfo<ArrayElementType<T>>;
|
|
55
|
+
/**
|
|
56
|
+
* Calculate array depth at runtime (fallback for type analysis)
|
|
57
|
+
*/
|
|
58
|
+
private static calculateArrayDepth;
|
|
59
|
+
/**
|
|
60
|
+
* Extract element type (for validation purposes)
|
|
61
|
+
*/
|
|
62
|
+
private static extractElementType;
|
|
63
|
+
/**
|
|
64
|
+
* Generate optimized validation function for multi-dimensional arrays
|
|
65
|
+
*/
|
|
66
|
+
static generateOptimizedValidator<T>(structure: ArrayStructureInfo<T>, fieldPath: string, elementValidator: (element: T, path: string) => ValidationResult): (array: any) => ValidationResult;
|
|
67
|
+
/**
|
|
68
|
+
* Create nested loop validator with arbitrary depth
|
|
69
|
+
*/
|
|
70
|
+
private static createNestedLoopValidator;
|
|
71
|
+
/**
|
|
72
|
+
* Generate nested loop code string
|
|
73
|
+
*/
|
|
74
|
+
private static generateNestedLoopCode;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validation result interface
|
|
78
|
+
*/
|
|
79
|
+
interface ValidationResult {
|
|
80
|
+
valid: boolean;
|
|
81
|
+
errors: Array<{
|
|
82
|
+
path: string;
|
|
83
|
+
code: string;
|
|
84
|
+
message: string;
|
|
85
|
+
}>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Type-safe array field validator generator
|
|
89
|
+
* Uses TypeScript type information to create optimized validators
|
|
90
|
+
*/
|
|
91
|
+
export declare function createTypedArrayValidator<T>(fieldPath: string, elementValidator: (element: ArrayElementType<T>, path: string) => ValidationResult): (value: T) => ValidationResult;
|
|
92
|
+
/**
|
|
93
|
+
* Compile-time type testing
|
|
94
|
+
*/
|
|
95
|
+
export type Test_ArrayDepth = {
|
|
96
|
+
Simple: ArrayDepth<string[]>;
|
|
97
|
+
Double: ArrayDepth<string[][]>;
|
|
98
|
+
Triple: ArrayDepth<string[][][]>;
|
|
99
|
+
Complex: ArrayDepth<Array<Array<{
|
|
100
|
+
id: number;
|
|
101
|
+
name: string;
|
|
102
|
+
}[]>>>;
|
|
103
|
+
};
|
|
104
|
+
export type Test_ElementType = {
|
|
105
|
+
Simple: ArrayElementType<{
|
|
106
|
+
name: string;
|
|
107
|
+
}[]>;
|
|
108
|
+
Double: ArrayElementType<{
|
|
109
|
+
name: string;
|
|
110
|
+
}[][]>;
|
|
111
|
+
Triple: ArrayElementType<{
|
|
112
|
+
name: string;
|
|
113
|
+
}[][][]>;
|
|
114
|
+
};
|
|
115
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal type definitions - only exports actually used in the codebase
|
|
3
|
+
* Optimized for bundle size by removing unused complex type definitions
|
|
4
|
+
*/
|
|
5
|
+
import { NestedKeyOf, TypeOfPath, ElementType } from "./util";
|
|
6
|
+
import { Result, LuqValidationException } from "./result";
|
|
7
|
+
export { Result, LuqValidationException };
|
|
8
|
+
/**
|
|
9
|
+
* Validation result interface - used in builder/types.ts
|
|
10
|
+
*/
|
|
11
|
+
export type ValidationResult<T> = {
|
|
12
|
+
valid: boolean;
|
|
13
|
+
value: T | null;
|
|
14
|
+
errors: ValidationError[];
|
|
15
|
+
originalValue?: T;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Validation error interface - used in plugin-registry.ts
|
|
19
|
+
*/
|
|
20
|
+
export type ValidationError = {
|
|
21
|
+
path: string;
|
|
22
|
+
message: string;
|
|
23
|
+
code: string;
|
|
24
|
+
paths(): string[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Message factory type - used in reporter.ts and plugin/types.ts
|
|
28
|
+
* Import from plugin/types for consistent definition
|
|
29
|
+
*/
|
|
30
|
+
import type { MessageFactory } from "../core/plugin/types";
|
|
31
|
+
export type { MessageFactory };
|
|
32
|
+
/**
|
|
33
|
+
* Validation options - used in registry and plugin-types
|
|
34
|
+
*/
|
|
35
|
+
export type ValidationOptions = {
|
|
36
|
+
/** Abort validation on first error (default: true) */
|
|
37
|
+
abortEarly?: boolean;
|
|
38
|
+
/** Abort validation on each field's first error (default: true) */
|
|
39
|
+
abortEarlyOnEachField?: boolean;
|
|
40
|
+
/** Custom message factory for error messages */
|
|
41
|
+
messageFactory?: MessageFactory;
|
|
42
|
+
/** Translation function for i18n support */
|
|
43
|
+
translate?: (key: string, params?: Record<string, any>) => string;
|
|
44
|
+
/** Context data passed to validators */
|
|
45
|
+
context?: Record<string, any>;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Parse options - used in registry and plugin-types
|
|
49
|
+
*/
|
|
50
|
+
export type ParseOptions = {
|
|
51
|
+
/** Abort parsing on first error (default: true) */
|
|
52
|
+
abortEarly?: boolean;
|
|
53
|
+
/** Abort parsing on each field's first error (default: true) */
|
|
54
|
+
abortEarlyOnEachField?: boolean;
|
|
55
|
+
/** Custom message factory for error messages */
|
|
56
|
+
messageFactory?: MessageFactory;
|
|
57
|
+
/** Translation function for i18n support */
|
|
58
|
+
translate?: (key: string, params?: Record<string, any>) => string;
|
|
59
|
+
/** Context data passed to validators */
|
|
60
|
+
context?: Record<string, any>;
|
|
61
|
+
/** Custom transform functions for post-processing */
|
|
62
|
+
transforms?: Record<string, (value: any) => any>;
|
|
63
|
+
};
|
|
64
|
+
export { NestedKeyOf, TypeOfPath, ElementType };
|
|
65
|
+
/**
|
|
66
|
+
* Union to intersection utility type - used in plugin/types.ts
|
|
67
|
+
*/
|
|
68
|
+
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
69
|
+
/**
|
|
70
|
+
* Validator interface - simplified version for compatibility
|
|
71
|
+
*/
|
|
72
|
+
export interface Validator<T> {
|
|
73
|
+
validate(value: unknown): ValidationResult<T>;
|
|
74
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True index-based Result implementation
|
|
3
|
+
* Stores only error index and generates error objects on demand
|
|
4
|
+
*/
|
|
5
|
+
import { ValidationError } from "./index";
|
|
6
|
+
import { Result } from "./result";
|
|
7
|
+
/**
|
|
8
|
+
* Error context for deferred error generation
|
|
9
|
+
*/
|
|
10
|
+
export interface ErrorContext {
|
|
11
|
+
path: string;
|
|
12
|
+
value: any;
|
|
13
|
+
validators?: any[];
|
|
14
|
+
errorGenerator?: (index: number, context: ErrorContext) => ValidationError;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Index-based validation state
|
|
18
|
+
*/
|
|
19
|
+
export interface IndexedValidState<T> {
|
|
20
|
+
readonly errorIndex: number;
|
|
21
|
+
readonly data?: T;
|
|
22
|
+
readonly errorContext?: ErrorContext;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create index-based Result implementation
|
|
26
|
+
*/
|
|
27
|
+
export declare function createIndexedResult<T>(state: IndexedValidState<T>): Result<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Index-based Result factory
|
|
30
|
+
*/
|
|
31
|
+
export declare const IndexedResult: {
|
|
32
|
+
/**
|
|
33
|
+
* Create a successful result
|
|
34
|
+
*/
|
|
35
|
+
ok<T>(data: T): Result<T>;
|
|
36
|
+
/**
|
|
37
|
+
* Create a failed result with error index
|
|
38
|
+
*/
|
|
39
|
+
errorIndex<T>(errorIndex: number, errorContext: ErrorContext): Result<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Create a failed result with pre-generated errors (for compatibility)
|
|
42
|
+
*/
|
|
43
|
+
error<T>(errors: ValidationError[]): Result<T>;
|
|
44
|
+
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result pattern implementation for Luq validation
|
|
3
|
+
* Provides a type-safe, functional approach to handling validation results
|
|
4
|
+
*/
|
|
5
|
+
import { ValidationError } from "./index";
|
|
6
|
+
/**
|
|
7
|
+
* Lightweight validation exception interface
|
|
8
|
+
*/
|
|
9
|
+
export interface LuqValidationException {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly errors: ValidationError[];
|
|
13
|
+
toString(): string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a validation exception (does not extend Error for performance)
|
|
17
|
+
*/
|
|
18
|
+
export declare function createLuqValidationException(message: string, errors: ValidationError[]): LuqValidationException;
|
|
19
|
+
export declare const LuqValidationException: {
|
|
20
|
+
new (message: string, errors: ValidationError[]): LuqValidationException;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Represents a successful validation result
|
|
24
|
+
*/
|
|
25
|
+
export interface ValidResult<T> {
|
|
26
|
+
readonly isValid: true;
|
|
27
|
+
readonly data: T;
|
|
28
|
+
readonly errors: never;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Represents a failed validation result
|
|
32
|
+
*/
|
|
33
|
+
export interface InvalidResult {
|
|
34
|
+
readonly isValid: false;
|
|
35
|
+
readonly data: never;
|
|
36
|
+
readonly errors: ValidationError[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Union type for validation results
|
|
40
|
+
*/
|
|
41
|
+
export type ValidationState<T> = ValidResult<T> | InvalidResult;
|
|
42
|
+
/**
|
|
43
|
+
* Result interface providing functional validation result handling
|
|
44
|
+
* Pattern 3: Function-based interface approach
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const result = validator.validate(data);
|
|
49
|
+
*
|
|
50
|
+
* // Check if valid
|
|
51
|
+
* if (result.isValid()) {
|
|
52
|
+
* // unwrap data safely
|
|
53
|
+
* const data = result.unwrap();
|
|
54
|
+
* }
|
|
55
|
+
*
|
|
56
|
+
* // Functional approach
|
|
57
|
+
* const processed = result
|
|
58
|
+
* .map(data => ({ ...data, processed: true }))
|
|
59
|
+
* .unwrapOr(defaultValue);
|
|
60
|
+
*
|
|
61
|
+
* // Exception approach
|
|
62
|
+
* const data = result.unwrap(); // throws if invalid
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export interface Result<T> {
|
|
66
|
+
/**
|
|
67
|
+
* Check if result is valid
|
|
68
|
+
*/
|
|
69
|
+
isValid(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Backward compatibility: Check if result is valid (property access)
|
|
72
|
+
*/
|
|
73
|
+
readonly valid: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Check if result is invalid
|
|
76
|
+
*/
|
|
77
|
+
isError(): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Get the data if valid, otherwise throw ValidationException
|
|
80
|
+
*
|
|
81
|
+
* @throws {LuqValidationException} If the result is invalid
|
|
82
|
+
*/
|
|
83
|
+
unwrap(): T;
|
|
84
|
+
/**
|
|
85
|
+
* Get the data if valid, otherwise return the default value
|
|
86
|
+
*/
|
|
87
|
+
unwrapOr(defaultValue: T): T;
|
|
88
|
+
/**
|
|
89
|
+
* Get the data if valid, otherwise compute default using lazy function
|
|
90
|
+
*/
|
|
91
|
+
unwrapOrElse(fn: (errors: ValidationError[]) => T): T;
|
|
92
|
+
/**
|
|
93
|
+
* Transform the data if valid, leave errors unchanged
|
|
94
|
+
*/
|
|
95
|
+
map<U>(fn: (data: T) => U): Result<U>;
|
|
96
|
+
/**
|
|
97
|
+
* Transform the data if valid, allowing for fallible transformation
|
|
98
|
+
*/
|
|
99
|
+
flatMap<U>(fn: (data: T) => Result<U>): Result<U>;
|
|
100
|
+
/**
|
|
101
|
+
* Execute a side effect if the result is valid
|
|
102
|
+
*/
|
|
103
|
+
tap(fn: (data: T) => void): Result<T>;
|
|
104
|
+
/**
|
|
105
|
+
* Execute a side effect if the result is invalid
|
|
106
|
+
*/
|
|
107
|
+
tapError(fn: (errors: ValidationError[]) => void): Result<T>;
|
|
108
|
+
/**
|
|
109
|
+
* Get the data if valid, undefined otherwise
|
|
110
|
+
* Use with caution - prefer unwrapOr() or check isValid() first
|
|
111
|
+
*/
|
|
112
|
+
data(): T | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Get the errors if invalid, empty array otherwise
|
|
115
|
+
*/
|
|
116
|
+
readonly errors: ValidationError[];
|
|
117
|
+
/**
|
|
118
|
+
* Convert to plain object (for serialization/compatibility)
|
|
119
|
+
*/
|
|
120
|
+
toPlainObject(): {
|
|
121
|
+
valid: boolean;
|
|
122
|
+
data?: T;
|
|
123
|
+
errors: ValidationError[];
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Result implementation factory
|
|
128
|
+
*/
|
|
129
|
+
export declare const Result: {
|
|
130
|
+
/**
|
|
131
|
+
* Create a successful result - optimized for performance
|
|
132
|
+
*/
|
|
133
|
+
ok<T>(data: T): Result<T>;
|
|
134
|
+
/**
|
|
135
|
+
* Create a failed result
|
|
136
|
+
*/
|
|
137
|
+
error<T>(errors: ValidationError[]): Result<T>;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Utility functions for working with Results
|
|
141
|
+
*/
|
|
142
|
+
export declare namespace ResultUtils {
|
|
143
|
+
/**
|
|
144
|
+
* Combine multiple results into a single result containing an array
|
|
145
|
+
* If any result is invalid, returns the first error
|
|
146
|
+
*/
|
|
147
|
+
function all<T>(results: Result<T>[]): Result<T[]>;
|
|
148
|
+
/**
|
|
149
|
+
* Return the first valid result, or all errors if none are valid
|
|
150
|
+
*/
|
|
151
|
+
function any<T>(results: Result<T>[]): Result<T>;
|
|
152
|
+
/**
|
|
153
|
+
* Partition results into valid and invalid arrays
|
|
154
|
+
*/
|
|
155
|
+
function partition<T>(results: Result<T>[]): {
|
|
156
|
+
valid: T[];
|
|
157
|
+
invalid: ValidationError[][];
|
|
158
|
+
};
|
|
159
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advanced type utilities for Stitch plugin - Multi-field reference type safety
|
|
3
|
+
*/
|
|
4
|
+
import { NestedKeyOf, TypeOfPath } from "./util";
|
|
5
|
+
/**
|
|
6
|
+
* Extract field types from an array of field paths into a typed object
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* type UserForm = { name: string; age: number; email: string; }
|
|
11
|
+
* type Fields = ["name", "age"]
|
|
12
|
+
* type Result = FieldsToObject<UserForm, Fields>
|
|
13
|
+
* // Result: { name: string; age: number; }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export type FieldsToObject<T, K extends readonly (NestedKeyOf<T> & string)[]> = {
|
|
17
|
+
[P in K[number]]: TypeOfPath<T, P>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* More precise tuple-based field extraction for better type inference
|
|
21
|
+
* Preserves the exact relationship between field positions and types
|
|
22
|
+
*/
|
|
23
|
+
export type TupleFieldsToObject<T, K extends readonly [...(NestedKeyOf<T> & string)[]]> = {
|
|
24
|
+
[Index in keyof K as K[Index] extends string ? K[Index] : never]: K[Index] extends NestedKeyOf<T> & string ? TypeOfPath<T, K[Index]> : never;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Type-safe Stitch validation function
|
|
28
|
+
* - First argument: Object containing only the specified field values with correct types
|
|
29
|
+
* - Second argument: Current field value with its inferred type
|
|
30
|
+
* - Third argument: Complete form object with full type safety
|
|
31
|
+
*/
|
|
32
|
+
export type StitchValidationFn<TObject, TCurrentField, TFields extends readonly (NestedKeyOf<TObject> & string)[]> = (fieldValues: FieldsToObject<TObject, TFields>, currentValue: TCurrentField, allValues: TObject) => {
|
|
33
|
+
valid: boolean;
|
|
34
|
+
message?: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Type-safe Stitch plugin options with complete type inference
|
|
38
|
+
*/
|
|
39
|
+
export type TypeSafeStitchOptions<TObject, TCurrentField, TFields extends readonly (NestedKeyOf<TObject> & string)[]> = {
|
|
40
|
+
/**
|
|
41
|
+
* Array of field paths - constrained to valid nested keys of TObject
|
|
42
|
+
* Must be readonly tuple for precise type inference
|
|
43
|
+
*/
|
|
44
|
+
fields: TFields;
|
|
45
|
+
/**
|
|
46
|
+
* Validation function with full type safety:
|
|
47
|
+
* - fieldValues: Extracted field types as typed object
|
|
48
|
+
* - currentValue: Current field's value with correct type
|
|
49
|
+
* - allValues: Complete form object
|
|
50
|
+
*/
|
|
51
|
+
validate: StitchValidationFn<TObject, TCurrentField, TFields>;
|
|
52
|
+
/** Optional custom error code */
|
|
53
|
+
code?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Optional custom error message factory with field context
|
|
56
|
+
*/
|
|
57
|
+
messageFactory?: (context: {
|
|
58
|
+
path: string;
|
|
59
|
+
value: TCurrentField;
|
|
60
|
+
code: string;
|
|
61
|
+
fields: TFields;
|
|
62
|
+
fieldValues: FieldsToObject<TObject, TFields>;
|
|
63
|
+
allValues: TObject;
|
|
64
|
+
}) => string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Helper type to validate that all fields exist in the object type
|
|
68
|
+
* Provides compile-time validation of field paths
|
|
69
|
+
*/
|
|
70
|
+
export type ValidateFieldPaths<T, K extends readonly string[]> = K extends readonly [...infer Fields] ? Fields extends readonly (NestedKeyOf<T> & string)[] ? K : never : never;
|
|
71
|
+
/**
|
|
72
|
+
* Utility type for creating strongly typed field references
|
|
73
|
+
* Ensures all field paths are valid at compile time
|
|
74
|
+
*/
|
|
75
|
+
export type CreateStitchOptions<T, TCurrentField> = <const TFields extends readonly (NestedKeyOf<T> & string)[]>(options: TypeSafeStitchOptions<T, TCurrentField, TFields>) => TypeSafeStitchOptions<T, TCurrentField, TFields>;
|
|
76
|
+
export declare const createStitchOptions: <T, TCurrentField>() => CreateStitchOptions<T, TCurrentField>;
|
|
77
|
+
/**
|
|
78
|
+
* Example usage and type validation:
|
|
79
|
+
*
|
|
80
|
+
* ```typescript
|
|
81
|
+
* type EventForm = {
|
|
82
|
+
* startDate: string;
|
|
83
|
+
* endDate: string;
|
|
84
|
+
* eventDate: string;
|
|
85
|
+
* price: number;
|
|
86
|
+
* quantity: number;
|
|
87
|
+
* taxRate?: number;
|
|
88
|
+
* }
|
|
89
|
+
*
|
|
90
|
+
* // Type-safe usage
|
|
91
|
+
* const eventDateValidator = Builder()
|
|
92
|
+
* .use(stitchPlugin)
|
|
93
|
+
* .for<EventForm>()
|
|
94
|
+
* .v("eventDate", (b) => b.string.required().stitch({
|
|
95
|
+
* fields: ["startDate", "endDate"] as const, // ← readonly tuple for exact inference
|
|
96
|
+
* validate: (fieldValues, eventDate, allValues) => {
|
|
97
|
+
* // fieldValues: { startDate: string; endDate: string; }
|
|
98
|
+
* // eventDate: string
|
|
99
|
+
* // allValues: EventForm
|
|
100
|
+
*
|
|
101
|
+
* const event = new Date(eventDate);
|
|
102
|
+
* const start = new Date(fieldValues.startDate); // ← Type-safe access
|
|
103
|
+
* const end = new Date(fieldValues.endDate); // ← Type-safe access
|
|
104
|
+
*
|
|
105
|
+
* // Can access any field from allValues with full type safety
|
|
106
|
+
* const taxRate = allValues.taxRate ?? 0; // ← Optional field handling
|
|
107
|
+
*
|
|
108
|
+
* return {
|
|
109
|
+
* valid: event >= start && event <= end,
|
|
110
|
+
* message: event < start
|
|
111
|
+
* ? "Event date cannot be before start date"
|
|
112
|
+
* : "Event date cannot be after end date"
|
|
113
|
+
* };
|
|
114
|
+
* }
|
|
115
|
+
* }))
|
|
116
|
+
* .build();
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Validator } from "./valitator";
|
|
2
|
+
export type InferType<T extends Validator<any, any>> = T extends Validator<infer U, infer U> ? U : never;
|
|
3
|
+
type IsPlainObject<T> = T extends object ? T extends Function ? false : T extends any[] ? false : T extends Date ? false : true : false;
|
|
4
|
+
type ArrayMethodNames = keyof any[] | keyof ReadonlyArray<any>;
|
|
5
|
+
type ExcludeArrayMethods<T> = T extends string ? T extends ArrayMethodNames ? never : T : T;
|
|
6
|
+
type ArrayElementPaths<U, Prefix extends string, D extends number> = U extends object ? {
|
|
7
|
+
[P in Extract<keyof U, string>]: U[P] extends Array<any> ? `${Prefix}.${P}` : NonNullable<U[P]> extends Array<any> ? `${Prefix}.${P}` : never;
|
|
8
|
+
}[Extract<keyof U, string>] : never;
|
|
9
|
+
type NestedKeyOfWithDepth<T, D extends number = 5> = D extends 0 ? never : T extends object ? {
|
|
10
|
+
[K in Extract<keyof T, string>]: T[K] extends Array<infer U> ? U extends Array<infer V> ? // 2D array case
|
|
11
|
+
K | `${K}[*]` | `${K}[*][*]` | (V extends object ? `${K}[*][*].${ExcludeArrayMethods<NestedKeyOfWithDepth<V, [-1, 0, 1, 2, 3, 4, 5][D]>>}` : never) : // 1D array case
|
|
12
|
+
K | `${K}[*]` | (U extends object ? `${K}[*].${ExcludeArrayMethods<NestedKeyOfWithDepth<U, [-1, 0, 1, 2, 3, 4, 5][D]>>}` : never) | ArrayElementPaths<U, `${K}[*]`, D> : NonNullable<T[K]> extends Array<infer U> ? U extends Array<infer V> ? // Optional 2D array case
|
|
13
|
+
K | `${K}[*]` | `${K}[*][*]` | (V extends object ? `${K}[*][*].${ExcludeArrayMethods<NestedKeyOfWithDepth<V, [-1, 0, 1, 2, 3, 4, 5][D]>>}` : never) : // Optional 1D array case
|
|
14
|
+
K | `${K}[*]` | (U extends object ? `${K}[*].${ExcludeArrayMethods<NestedKeyOfWithDepth<U, [-1, 0, 1, 2, 3, 4, 5][D]>>}` : never) | ArrayElementPaths<U, `${K}[*]`, D> : NonNullable<T[K]> extends object ? IsPlainObject<NonNullable<T[K]>> extends true ? K | `${K}.${NestedKeyOfWithDepth<NonNullable<T[K]>, [-1, 0, 1, 2, 3, 4, 5][D]>}` : K : K;
|
|
15
|
+
}[Extract<keyof T, string>] : never;
|
|
16
|
+
export type NestedKeyOf<T> = NestedKeyOfWithDepth<T>;
|
|
17
|
+
export type TypeOfPath<T, Path extends string> = Path extends `${infer K}[*][*][*]` ? K extends keyof T ? T[K] extends Array<Array<Array<infer U>>> ? U : never : never : Path extends `${infer K}[*][*]` ? K extends keyof T ? T[K] extends Array<Array<infer U>> ? U : never : never : Path extends `${infer K}[*]` ? K extends keyof T ? T[K] extends Array<infer U> ? U : never : never : Path extends `${infer K}.*` ? K extends keyof T ? T[K] extends Array<infer U> ? U : never : never : Path extends `${infer K}[*][*][*].${infer Rest}` ? K extends keyof T ? T[K] extends Array<Array<Array<infer U>>> ? TypeOfPath<U, Rest> : never : never : Path extends `${infer K}[*][*].${infer Rest}` ? K extends keyof T ? T[K] extends Array<Array<infer U>> ? TypeOfPath<U, Rest> : never : never : Path extends `${infer K}[*].${infer Rest}` ? K extends keyof T ? T[K] extends Array<infer U> ? TypeOfPath<U, Rest> : never : never : Path extends `${infer K}.*.${infer Rest}` ? K extends keyof T ? T[K] extends Array<infer U> ? TypeOfPath<U, Rest> : never : never : Path extends `${infer K}.${infer Rest}` ? K extends keyof T ? T[K] extends Array<infer U> ? TypeOfPath<U, Rest> : T[K] extends any ? TypeOfPath<T[K], Rest> : never : never : Path extends keyof T ? T[Path] : never;
|
|
18
|
+
export type ElementType<T> = T extends Array<infer U> ? U : never;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ValidationOptions, ValidationResult } from ".";
|
|
2
|
+
export interface Validator<TObject, TValue> {
|
|
3
|
+
validate(value: TValue, options?: ValidationOptions): ValidationResult<TValue>;
|
|
4
|
+
}
|
|
5
|
+
export interface FieldValidator<TObject, TValue, TRequiredKeys extends keyof TObject = never> {
|
|
6
|
+
validate(value: unknown, allValues: TRequiredKeys extends never ? TObject | undefined : TObject, options?: ValidationOptions): ValidationResult<TValue>;
|
|
7
|
+
}
|
|
8
|
+
export interface ValidatorStrategy<TObject, TValue> {
|
|
9
|
+
validate(value: unknown, options?: ValidationOptions): ValidationResult<TValue>;
|
|
10
|
+
}
|