MCPcopy Create free account
hub / github.com/RtlZeroMemory/Rezi / createDebouncedAsyncValidator

Function createDebouncedAsyncValidator

packages/core/src/forms/validation.ts:106–159  ·  view source on GitHub ↗
(
  validateAsync: (values: T) => Promise<ValidationResult<T>>,
  debounceMs: number,
  onResult: (errors: ValidationResult<T>) => void,
  onError?: (error: unknown) => void,
)

Source from the content-addressed store, hash-verified

104 * @returns Object with run and cancel methods
105 */
106export function createDebouncedAsyncValidator<T extends Record<string, unknown>>(
107 validateAsync: (values: T) => Promise<ValidationResult<T>>,
108 debounceMs: number,
109 onResult: (errors: ValidationResult<T>) => void,
110 onError?: (error: unknown) => void,
111): Readonly<{
112 run: (values: T) => void;
113 cancel: () => void;
114}> {
115 let timeoutId: ReturnType<typeof setTimeout> | undefined;
116 let cancelled = false;
117 // Monotonic token used to ignore stale debounced callbacks and in-flight promises.
118 let token = 0;
119
120 return Object.freeze({
121 run(values: T): void {
122 // Cancel any pending validation
123 if (timeoutId !== undefined) {
124 clearTimeout(timeoutId);
125 }
126 cancelled = false;
127 token++;
128 const myToken = token;
129
130 timeoutId = setTimeout(() => {
131 if (cancelled || myToken !== token) return;
132
133 validateAsync(values)
134 .then((errors) => {
135 if (!cancelled && myToken === token) {
136 onResult(errors);
137 }
138 })
139 .catch((e) => {
140 if (cancelled || myToken !== token) return;
141 if (onError) {
142 onError(e);
143 } else {
144 onResult({});
145 }
146 });
147 }, debounceMs);
148 },
149
150 cancel(): void {
151 cancelled = true;
152 token++;
153 if (timeoutId !== undefined) {
154 clearTimeout(timeoutId);
155 timeoutId = undefined;
156 }
157 },
158 });
159}
160
161/**
162 * Run async validation immediately (without debounce).

Callers 3

useFormFunction · 0.85
useForm.test.tsFile · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected