@tanstack/form-core 0.42.1 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/cjs/FieldApi.cjs +17 -28
  2. package/dist/cjs/FieldApi.cjs.map +1 -1
  3. package/dist/cjs/FieldApi.d.cts +91 -79
  4. package/dist/cjs/FormApi.cjs +50 -53
  5. package/dist/cjs/FormApi.cjs.map +1 -1
  6. package/dist/cjs/FormApi.d.cts +74 -67
  7. package/dist/cjs/formOptions.cjs.map +1 -1
  8. package/dist/cjs/formOptions.d.cts +2 -3
  9. package/dist/cjs/index.cjs +2 -1
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/mergeForm.cjs.map +1 -1
  12. package/dist/cjs/mergeForm.d.cts +1 -2
  13. package/dist/cjs/metaHelper.cjs.map +1 -1
  14. package/dist/cjs/metaHelper.d.cts +2 -3
  15. package/dist/cjs/standardSchemaValidator.cjs +24 -31
  16. package/dist/cjs/standardSchemaValidator.cjs.map +1 -1
  17. package/dist/cjs/standardSchemaValidator.d.cts +24 -4
  18. package/dist/cjs/types.d.cts +15 -27
  19. package/dist/cjs/util-types.d.cts +1 -0
  20. package/dist/cjs/utils.cjs +4 -0
  21. package/dist/cjs/utils.cjs.map +1 -1
  22. package/dist/cjs/utils.d.cts +4 -3
  23. package/dist/esm/FieldApi.d.ts +91 -79
  24. package/dist/esm/FieldApi.js +18 -29
  25. package/dist/esm/FieldApi.js.map +1 -1
  26. package/dist/esm/FormApi.d.ts +74 -67
  27. package/dist/esm/FormApi.js +52 -55
  28. package/dist/esm/FormApi.js.map +1 -1
  29. package/dist/esm/formOptions.d.ts +2 -3
  30. package/dist/esm/formOptions.js.map +1 -1
  31. package/dist/esm/index.js +4 -3
  32. package/dist/esm/mergeForm.d.ts +1 -2
  33. package/dist/esm/mergeForm.js.map +1 -1
  34. package/dist/esm/metaHelper.d.ts +2 -3
  35. package/dist/esm/metaHelper.js.map +1 -1
  36. package/dist/esm/standardSchemaValidator.d.ts +24 -4
  37. package/dist/esm/standardSchemaValidator.js +24 -31
  38. package/dist/esm/standardSchemaValidator.js.map +1 -1
  39. package/dist/esm/types.d.ts +15 -27
  40. package/dist/esm/util-types.d.ts +1 -0
  41. package/dist/esm/utils.d.ts +4 -3
  42. package/dist/esm/utils.js +4 -0
  43. package/dist/esm/utils.js.map +1 -1
  44. package/package.json +2 -2
  45. package/src/FieldApi.ts +803 -273
  46. package/src/FormApi.ts +613 -183
  47. package/src/formOptions.ts +26 -4
  48. package/src/mergeForm.ts +5 -7
  49. package/src/metaHelper.ts +28 -6
  50. package/src/standardSchemaValidator.ts +47 -58
  51. package/src/types.ts +39 -34
  52. package/src/util-types.ts +2 -0
  53. package/src/utils.ts +15 -9
@@ -1 +1 @@
1
- {"version":3,"file":"standardSchemaValidator.js","sources":["../../src/standardSchemaValidator.ts"],"sourcesContent":["import type {\n ValidationError,\n Validator,\n ValidatorAdapterParams,\n} from './types'\n\ntype Params = ValidatorAdapterParams<StandardSchemaV1Issue>\ntype TransformFn = NonNullable<Params['transformErrors']>\n\nfunction prefixSchemaToErrors(\n issues: readonly StandardSchemaV1Issue[],\n transformErrors: TransformFn,\n) {\n const schema = new Map<string, StandardSchemaV1Issue[]>()\n\n for (const issue of issues) {\n const path = [...(issue.path ?? [])]\n .map((segment) => {\n const normalizedSegment =\n typeof segment === 'object' ? segment.key : segment\n return typeof normalizedSegment === 'number'\n ? `[${normalizedSegment}]`\n : normalizedSegment\n })\n .join('.')\n .replace(/\\.\\[/g, '[')\n\n schema.set(path, (schema.get(path) ?? []).concat(issue))\n }\n\n const transformedSchema = {} as Record<string, ValidationError>\n\n schema.forEach((value, key) => {\n transformedSchema[key] = transformErrors(value)\n })\n\n return transformedSchema\n}\n\nfunction defaultFormTransformer(transformErrors: TransformFn) {\n return (issues: readonly StandardSchemaV1Issue[]) => ({\n form: transformErrors(issues as StandardSchemaV1Issue[]),\n fields: prefixSchemaToErrors(issues, transformErrors),\n })\n}\n\nexport const standardSchemaValidator =\n (params: Params = {}): Validator<unknown, StandardSchemaV1<any>> =>\n () => {\n const transformFieldErrors =\n params.transformErrors ??\n ((issues: StandardSchemaV1Issue[]) =>\n issues.map((issue) => issue.message).join(', '))\n\n const getTransformStrategy = (validationSource: 'form' | 'field') =>\n validationSource === 'form'\n ? defaultFormTransformer(transformFieldErrors)\n : transformFieldErrors\n\n return {\n validate({ value, validationSource }, fn) {\n const result = fn['~standard'].validate(value)\n\n if (result instanceof Promise) {\n throw new Error('async function passed to sync validator')\n }\n\n if (!result.issues) return\n\n const transformer = getTransformStrategy(validationSource)\n\n return transformer(result.issues as StandardSchemaV1Issue[])\n },\n async validateAsync({ value, validationSource }, fn) {\n const result = await fn['~standard'].validate(value)\n\n if (!result.issues) return\n\n const transformer = getTransformStrategy(validationSource)\n\n return transformer(result.issues as StandardSchemaV1Issue[])\n },\n }\n }\n\nexport const isStandardSchemaValidator = (\n validator: unknown,\n): validator is StandardSchemaV1 =>\n !!validator && '~standard' in (validator as object)\n\n/**\n * The Standard Schema interface.\n */\nexport type StandardSchemaV1<Input = unknown, Output = Input> = {\n /**\n * The Standard Schema properties.\n */\n readonly '~standard': StandardSchemaV1Props<Input, Output>\n}\n\n/**\n * The Standard Schema properties interface.\n */\ninterface StandardSchemaV1Props<Input = unknown, Output = Input> {\n /**\n * The version number of the standard.\n */\n readonly version: 1\n /**\n * The vendor name of the schema library.\n */\n readonly vendor: string\n /**\n * Validates unknown input values.\n */\n readonly validate: (\n value: unknown,\n ) => StandardSchemaV1Result<Output> | Promise<StandardSchemaV1Result<Output>>\n /**\n * Inferred types associated with the schema.\n */\n readonly types?: StandardSchemaV1Types<Input, Output> | undefined\n}\n/**\n * The result interface of the validate function.\n */\ntype StandardSchemaV1Result<Output> =\n | StandardSchemaV1SuccessResult<Output>\n | StandardSchemaV1FailureResult\n/**\n * The result interface if validation succeeds.\n */\ninterface StandardSchemaV1SuccessResult<Output> {\n /**\n * The typed output value.\n */\n readonly value: Output\n /**\n * The non-existent issues.\n */\n readonly issues?: undefined\n}\n/**\n * The result interface if validation fails.\n */\ninterface StandardSchemaV1FailureResult {\n /**\n * The issues of failed validation.\n */\n readonly issues: ReadonlyArray<StandardSchemaV1Issue>\n}\n/**\n * The issue interface of the failure output.\n */\ninterface StandardSchemaV1Issue {\n /**\n * The error message of the issue.\n */\n readonly message: string\n /**\n * The path of the issue, if any.\n */\n readonly path?:\n | ReadonlyArray<PropertyKey | StandardSchemaV1PathSegment>\n | undefined\n}\n/**\n * The path segment interface of the issue.\n */\ninterface StandardSchemaV1PathSegment {\n /**\n * The key representing a path segment.\n */\n readonly key: PropertyKey\n}\n/**\n * The Standard Schema types interface.\n */\ninterface StandardSchemaV1Types<Input = unknown, Output = Input> {\n /**\n * The input type of the schema.\n */\n readonly input: Input\n /**\n * The output type of the schema.\n */\n readonly output: Output\n}\n"],"names":[],"mappings":"AASA,SAAS,qBACP,QACA,iBACA;AACM,QAAA,6BAAa,IAAqC;AAExD,aAAW,SAAS,QAAQ;AACpB,UAAA,OAAO,CAAC,GAAI,MAAM,QAAQ,CAAA,CAAG,EAChC,IAAI,CAAC,YAAY;AAChB,YAAM,oBACJ,OAAO,YAAY,WAAW,QAAQ,MAAM;AAC9C,aAAO,OAAO,sBAAsB,WAChC,IAAI,iBAAiB,MACrB;AAAA,IAAA,CACL,EACA,KAAK,GAAG,EACR,QAAQ,SAAS,GAAG;AAEhB,WAAA,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC;AAAA,EAAA;AAGzD,QAAM,oBAAoB,CAAC;AAEpB,SAAA,QAAQ,CAAC,OAAO,QAAQ;AACX,sBAAA,GAAG,IAAI,gBAAgB,KAAK;AAAA,EAAA,CAC/C;AAEM,SAAA;AACT;AAEA,SAAS,uBAAuB,iBAA8B;AAC5D,SAAO,CAAC,YAA8C;AAAA,IACpD,MAAM,gBAAgB,MAAiC;AAAA,IACvD,QAAQ,qBAAqB,QAAQ,eAAe;AAAA,EAAA;AAExD;AAEO,MAAM,0BACX,CAAC,SAAiB,CAAA,MAClB,MAAM;AACJ,QAAM,uBACJ,OAAO,oBACN,CAAC,WACA,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI;AAElD,QAAM,uBAAuB,CAAC,qBAC5B,qBAAqB,SACjB,uBAAuB,oBAAoB,IAC3C;AAEC,SAAA;AAAA,IACL,SAAS,EAAE,OAAO,iBAAA,GAAoB,IAAI;AACxC,YAAM,SAAS,GAAG,WAAW,EAAE,SAAS,KAAK;AAE7C,UAAI,kBAAkB,SAAS;AACvB,cAAA,IAAI,MAAM,yCAAyC;AAAA,MAAA;AAGvD,UAAA,CAAC,OAAO,OAAQ;AAEd,YAAA,cAAc,qBAAqB,gBAAgB;AAElD,aAAA,YAAY,OAAO,MAAiC;AAAA,IAC7D;AAAA,IACA,MAAM,cAAc,EAAE,OAAO,iBAAA,GAAoB,IAAI;AACnD,YAAM,SAAS,MAAM,GAAG,WAAW,EAAE,SAAS,KAAK;AAE/C,UAAA,CAAC,OAAO,OAAQ;AAEd,YAAA,cAAc,qBAAqB,gBAAgB;AAElD,aAAA,YAAY,OAAO,MAAiC;AAAA,IAAA;AAAA,EAE/D;AACF;AAEK,MAAM,4BAA4B,CACvC,cAEA,CAAC,CAAC,aAAa,eAAgB;"}
1
+ {"version":3,"file":"standardSchemaValidator.js","sources":["../../src/standardSchemaValidator.ts"],"sourcesContent":["import type { ValidationSource } from './types'\n\nexport type TStandardSchemaValidatorValue<TData> = {\n value: TData\n validationSource: ValidationSource\n}\n\nfunction prefixSchemaToErrors(issues: readonly StandardSchemaV1Issue[]) {\n const schema = new Map<string, StandardSchemaV1Issue[]>()\n\n for (const issue of issues) {\n const path = [...(issue.path ?? [])]\n .map((segment) => {\n const normalizedSegment =\n typeof segment === 'object' ? segment.key : segment\n return typeof normalizedSegment === 'number'\n ? `[${normalizedSegment}]`\n : normalizedSegment\n })\n .join('.')\n .replace(/\\.\\[/g, '[')\n\n schema.set(path, (schema.get(path) ?? []).concat(issue))\n }\n\n return Object.fromEntries(schema)\n}\n\nconst defaultFieldTransformer = (issues: readonly StandardSchemaV1Issue[]) =>\n issues\n\nconst defaultFormTransformer = (issues: readonly StandardSchemaV1Issue[]) => {\n const schemaErrors = prefixSchemaToErrors(issues)\n return {\n form: schemaErrors,\n fields: schemaErrors,\n }\n}\n\nconst transformIssues = (\n validationSource: 'form' | 'field',\n issues: readonly StandardSchemaV1Issue[],\n) =>\n validationSource === 'form'\n ? defaultFormTransformer(issues)\n : defaultFieldTransformer(issues)\n\nexport const standardSchemaValidators = {\n validate(\n { value, validationSource }: TStandardSchemaValidatorValue<unknown>,\n schema: StandardSchemaV1,\n ) {\n const result = schema['~standard'].validate(value)\n\n if (result instanceof Promise) {\n throw new Error('async function passed to sync validator')\n }\n\n if (!result.issues) return\n\n return transformIssues(validationSource, result.issues)\n },\n async validateAsync(\n { value, validationSource }: TStandardSchemaValidatorValue<unknown>,\n schema: StandardSchemaV1,\n ) {\n const result = await schema['~standard'].validate(value)\n\n if (!result.issues) return\n\n return transformIssues(validationSource, result.issues)\n },\n}\n\nexport const isStandardSchemaValidator = (\n validator: unknown,\n): validator is StandardSchemaV1 =>\n !!validator && '~standard' in (validator as object)\n\n/**\n * The Standard Schema interface.\n */\nexport type StandardSchemaV1<Input = unknown, Output = Input> = {\n /**\n * The Standard Schema properties.\n */\n readonly '~standard': StandardSchemaV1Props<Input, Output>\n}\n\n/**\n * The Standard Schema properties interface.\n */\ninterface StandardSchemaV1Props<Input = unknown, Output = Input> {\n /**\n * The version number of the standard.\n */\n readonly version: 1\n /**\n * The vendor name of the schema library.\n */\n readonly vendor: string\n /**\n * Validates unknown input values.\n */\n readonly validate: (\n value: unknown,\n ) => StandardSchemaV1Result<Output> | Promise<StandardSchemaV1Result<Output>>\n /**\n * Inferred types associated with the schema.\n */\n readonly types?: StandardSchemaV1Types<Input, Output> | undefined\n}\n/**\n * The result interface of the validate function.\n */\ntype StandardSchemaV1Result<Output> =\n | StandardSchemaV1SuccessResult<Output>\n | StandardSchemaV1FailureResult\n/**\n * The result interface if validation succeeds.\n */\ninterface StandardSchemaV1SuccessResult<Output> {\n /**\n * The typed output value.\n */\n readonly value: Output\n /**\n * The non-existent issues.\n */\n readonly issues?: undefined\n}\n/**\n * The result interface if validation fails.\n */\ninterface StandardSchemaV1FailureResult {\n /**\n * The issues of failed validation.\n */\n readonly issues: ReadonlyArray<StandardSchemaV1Issue>\n}\n/**\n * The issue interface of the failure output.\n */\nexport interface StandardSchemaV1Issue {\n /**\n * The error message of the issue.\n */\n readonly message: string\n /**\n * The path of the issue, if any.\n */\n readonly path?:\n | ReadonlyArray<PropertyKey | StandardSchemaV1PathSegment>\n | undefined\n}\n/**\n * The path segment interface of the issue.\n */\ninterface StandardSchemaV1PathSegment {\n /**\n * The key representing a path segment.\n */\n readonly key: PropertyKey\n}\n/**\n * The Standard Schema types interface.\n */\ninterface StandardSchemaV1Types<Input = unknown, Output = Input> {\n /**\n * The input type of the schema.\n */\n readonly input: Input\n /**\n * The output type of the schema.\n */\n readonly output: Output\n}\n"],"names":[],"mappings":"AAOA,SAAS,qBAAqB,QAA0C;AAChE,QAAA,6BAAa,IAAqC;AAExD,aAAW,SAAS,QAAQ;AACpB,UAAA,OAAO,CAAC,GAAI,MAAM,QAAQ,CAAA,CAAG,EAChC,IAAI,CAAC,YAAY;AAChB,YAAM,oBACJ,OAAO,YAAY,WAAW,QAAQ,MAAM;AAC9C,aAAO,OAAO,sBAAsB,WAChC,IAAI,iBAAiB,MACrB;AAAA,IAAA,CACL,EACA,KAAK,GAAG,EACR,QAAQ,SAAS,GAAG;AAEhB,WAAA,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC;AAAA,EAAA;AAGlD,SAAA,OAAO,YAAY,MAAM;AAClC;AAEA,MAAM,0BAA0B,CAAC,WAC/B;AAEF,MAAM,yBAAyB,CAAC,WAA6C;AACrE,QAAA,eAAe,qBAAqB,MAAM;AACzC,SAAA;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACF;AAEA,MAAM,kBAAkB,CACtB,kBACA,WAEA,qBAAqB,SACjB,uBAAuB,MAAM,IAC7B,wBAAwB,MAAM;AAE7B,MAAM,2BAA2B;AAAA,EACtC,SACE,EAAE,OAAO,iBAAA,GACT,QACA;AACA,UAAM,SAAS,OAAO,WAAW,EAAE,SAAS,KAAK;AAEjD,QAAI,kBAAkB,SAAS;AACvB,YAAA,IAAI,MAAM,yCAAyC;AAAA,IAAA;AAGvD,QAAA,CAAC,OAAO,OAAQ;AAEb,WAAA,gBAAgB,kBAAkB,OAAO,MAAM;AAAA,EACxD;AAAA,EACA,MAAM,cACJ,EAAE,OAAO,iBAAA,GACT,QACA;AACA,UAAM,SAAS,MAAM,OAAO,WAAW,EAAE,SAAS,KAAK;AAEnD,QAAA,CAAC,OAAO,OAAQ;AAEb,WAAA,gBAAgB,kBAAkB,OAAO,MAAM;AAAA,EAAA;AAE1D;AAEO,MAAM,4BAA4B,CACvC,cAEA,CAAC,CAAC,aAAa,eAAgB;"}
@@ -1,27 +1,6 @@
1
1
  import { DeepKeys } from './util-types.js';
2
- export type ValidationError = undefined | false | null | string;
2
+ export type ValidationError = unknown;
3
3
  export type ValidationSource = 'form' | 'field';
4
- /**
5
- * If/when TypeScript supports higher-kinded types, this should not be `unknown` anymore
6
- * @private
7
- */
8
- export type Validator<Type, Fn = unknown> = () => {
9
- validate(options: {
10
- value: Type;
11
- validationSource: ValidationSource;
12
- }, fn: Fn): ValidationError | FormValidationError<unknown>;
13
- validateAsync(options: {
14
- value: Type;
15
- validationSource: ValidationSource;
16
- }, fn: Fn): Promise<ValidationError | FormValidationError<unknown>>;
17
- };
18
- /**
19
- * Parameters in common for all validator adapters, making it easier to swap adapter
20
- * @private
21
- */
22
- export type ValidatorAdapterParams<TError = unknown> = {
23
- transformErrors?: (errors: TError[]) => ValidationError;
24
- };
25
4
  /**
26
5
  * "server" is only intended for SSR/SSG validation and should not execute anything
27
6
  * @private
@@ -34,15 +13,24 @@ export type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`;
34
13
  /**
35
14
  * @private
36
15
  */
37
- export type ValidationErrorMap = {
38
- [K in ValidationErrorMapKeys]?: ValidationError;
16
+ export type ValidationErrorMap<TOnMountReturn = unknown, TOnChangeReturn = unknown, TOnChangeAsyncReturn = unknown, TOnBlurReturn = unknown, TOnBlurAsyncReturn = unknown, TOnSubmitReturn = unknown, TOnSubmitAsyncReturn = unknown, TOnServerReturn = unknown> = {
17
+ onMount?: TOnMountReturn;
18
+ onChange?: TOnChangeReturn | TOnChangeAsyncReturn;
19
+ onBlur?: TOnBlurReturn | TOnBlurAsyncReturn;
20
+ onSubmit?: TOnSubmitReturn | TOnSubmitAsyncReturn;
21
+ onServer?: TOnServerReturn;
39
22
  };
40
23
  /**
41
24
  * @private
42
25
  */
43
- export type FormValidationErrorMap = {
44
- [K in ValidationErrorMapKeys]?: ValidationError | FormValidationError<unknown>;
26
+ export type FormValidationErrorMap<TOnMountReturn = unknown, TOnChangeReturn = unknown, TOnChangeAsyncReturn = unknown, TOnBlurReturn = unknown, TOnBlurAsyncReturn = unknown, TOnSubmitReturn = unknown, TOnSubmitAsyncReturn = unknown, TOnServerReturn = unknown> = {
27
+ onMount?: TOnMountReturn;
28
+ onChange?: TOnChangeReturn | TOnChangeAsyncReturn;
29
+ onBlur?: TOnBlurReturn | TOnBlurAsyncReturn;
30
+ onSubmit?: TOnSubmitReturn | TOnSubmitAsyncReturn;
31
+ onServer?: TOnServerReturn;
45
32
  };
33
+ export type FormValidationError<TFormData> = ValidationError | GlobalFormValidationError<TFormData>;
46
34
  /**
47
35
  * @private
48
36
  *
@@ -56,7 +44,7 @@ export type FormValidationErrorMap = {
56
44
  * }
57
45
  * ````
58
46
  */
59
- export type FormValidationError<TFormData> = ValidationError | {
47
+ export type GlobalFormValidationError<TFormData> = {
60
48
  form?: ValidationError;
61
49
  fields: Partial<Record<DeepKeys<TFormData>, ValidationError>>;
62
50
  };
@@ -1,5 +1,6 @@
1
1
  type Nullable<T> = T | null;
2
2
  type IsNullable<T> = [null] extends [T] ? true : false;
3
+ export type UnwrapOneLevelOfArray<T> = T extends (infer U)[] ? U : T;
3
4
  /**
4
5
  * @private
5
6
  */
@@ -1,4 +1,4 @@
1
- import { ValidationCause } from './types.js';
1
+ import { GlobalFormValidationError, ValidationCause } from './types.js';
2
2
  import { FormValidators } from './FormApi.js';
3
3
  import { FieldValidators } from './FieldApi.js';
4
4
  export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput;
@@ -45,7 +45,7 @@ export interface AsyncValidator<T> {
45
45
  /**
46
46
  * @private
47
47
  */
48
- export declare function getAsyncValidatorArray<T>(cause: ValidationCause, options: AsyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : T extends FormValidators<any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : never;
48
+ export declare function getAsyncValidatorArray<T>(cause: ValidationCause, options: AsyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : T extends FormValidators<any, any, any, any, any, any, any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : never;
49
49
  interface SyncValidatorArrayPartialOptions<T> {
50
50
  validators?: T;
51
51
  }
@@ -59,6 +59,7 @@ export interface SyncValidator<T> {
59
59
  /**
60
60
  * @private
61
61
  */
62
- export declare function getSyncValidatorArray<T>(cause: ValidationCause, options: SyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>> : T extends FormValidators<any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>> : never;
62
+ export declare function getSyncValidatorArray<T>(cause: ValidationCause, options: SyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>> : T extends FormValidators<any, any, any, any, any, any, any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>> : never;
63
+ export declare const isGlobalFormValidationError: (error: unknown) => error is GlobalFormValidationError<unknown>;
63
64
  export declare function shallow<T>(objA: T, objB: T): boolean;
64
65
  export {};
package/dist/esm/utils.js CHANGED
@@ -177,6 +177,9 @@ function getSyncValidatorArray(cause, options) {
177
177
  return [changeValidator, serverValidator];
178
178
  }
179
179
  }
180
+ const isGlobalFormValidationError = (error) => {
181
+ return !!error && typeof error === "object" && "fields" in error;
182
+ };
180
183
  function shallow(objA, objB) {
181
184
  if (Object.is(objA, objB)) {
182
185
  return true;
@@ -215,6 +218,7 @@ export {
215
218
  getAsyncValidatorArray,
216
219
  getBy,
217
220
  getSyncValidatorArray,
221
+ isGlobalFormValidationError,
218
222
  isNonEmptyArray,
219
223
  makePathArray,
220
224
  setBy,
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import type { ValidationCause } from './types'\nimport type { FormValidators } from './FormApi'\nimport type { FieldValidators } from './FieldApi'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\n/**\n * @private\n */\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n * @private\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (current === null) return null\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n * @private\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\n if (typeof parent === 'object') {\n if (parent === null) {\n parent = {}\n }\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && typeof key === 'number') {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n * @private\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (!parent) return\n if (path.length === 1) {\n const finalPath = path[0]!\n if (Array.isArray(parent) && typeof finalPath === 'number') {\n return parent.filter((_, i) => i !== finalPath)\n }\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n if (key >= parent.length) {\n return parent\n }\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\n/**\n * @private\n */\nexport function makePathArray(str: string | Array<string | number>) {\n if (Array.isArray(str)) {\n return [...str]\n }\n\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replaceAll('[', '.')\n .replaceAll(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\n/**\n * @private\n */\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\n/**\n * @private\n */\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<any, any>\n ? Array<\n AsyncValidator<\n T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<any, any>\n | FormValidators<any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const changeValidator = {\n cause: 'change',\n validate: onChangeAsync,\n debounceMs: onChangeAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const blurValidator = {\n cause: 'blur',\n validate: onBlurAsync,\n debounceMs: onBlurAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const submitValidator = {\n cause: 'submit',\n validate: onSubmitAsync,\n debounceMs: 0,\n } as const\n\n const noopValidator = (\n validator:\n | typeof changeValidator\n | typeof blurValidator\n | typeof submitValidator,\n ) => ({ ...validator, debounceMs: 0 }) as const\n\n switch (cause) {\n case 'submit':\n return [\n noopValidator(changeValidator),\n noopValidator(blurValidator),\n submitValidator,\n ] as never\n case 'blur':\n return [blurValidator] as never\n case 'change':\n return [changeValidator] as never\n case 'server':\n default:\n return [] as never\n }\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\n/**\n * @private\n */\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\n/**\n * @private\n */\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any>\n ? Array<\n SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>\n >\n : T extends FormValidators<any, any>\n ? Array<\n SyncValidator<\n T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']\n >\n >\n : never {\n const { onChange, onBlur, onSubmit, onMount } = (options.validators || {}) as\n | FieldValidators<any, any>\n | FormValidators<any, any>\n\n const changeValidator = { cause: 'change', validate: onChange } as const\n const blurValidator = { cause: 'blur', validate: onBlur } as const\n const submitValidator = { cause: 'submit', validate: onSubmit } as const\n const mountValidator = { cause: 'mount', validate: onMount } as const\n\n // Allows us to clear onServer errors\n const serverValidator = {\n cause: 'server',\n validate: () => undefined,\n } as const\n\n switch (cause) {\n case 'mount':\n return [mountValidator] as never\n case 'submit':\n return [\n changeValidator,\n blurValidator,\n submitValidator,\n serverValidator,\n ] as never\n case 'server':\n return [serverValidator] as never\n case 'blur':\n return [blurValidator, serverValidator] as never\n case 'change':\n default:\n return [changeValidator, serverValidator] as never\n }\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false\n for (const [k, v] of objA) {\n if (!objB.has(k) || !Object.is(v, objB.get(k))) return false\n }\n return true\n }\n\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false\n for (const v of objA) {\n if (!objB.has(v)) return false\n }\n return true\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import type { GlobalFormValidationError, ValidationCause } from './types'\nimport type { FormValidators } from './FormApi'\nimport type { FieldValidators } from './FieldApi'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\n/**\n * @private\n */\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n * @private\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (current === null) return null\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n * @private\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\n if (typeof parent === 'object') {\n if (parent === null) {\n parent = {}\n }\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && typeof key === 'number') {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n * @private\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (!parent) return\n if (path.length === 1) {\n const finalPath = path[0]!\n if (Array.isArray(parent) && typeof finalPath === 'number') {\n return parent.filter((_, i) => i !== finalPath)\n }\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n if (key >= parent.length) {\n return parent\n }\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\n/**\n * @private\n */\nexport function makePathArray(str: string | Array<string | number>) {\n if (Array.isArray(str)) {\n return [...str]\n }\n\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replaceAll('[', '.')\n .replaceAll(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\n/**\n * @private\n */\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\n/**\n * @private\n */\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<any, any, any, any, any, any, any, any, any, any>\n | FormValidators<any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const changeValidator = {\n cause: 'change',\n validate: onChangeAsync,\n debounceMs: onChangeAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const blurValidator = {\n cause: 'blur',\n validate: onBlurAsync,\n debounceMs: onBlurAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const submitValidator = {\n cause: 'submit',\n validate: onSubmitAsync,\n debounceMs: 0,\n } as const\n\n const noopValidator = (\n validator:\n | typeof changeValidator\n | typeof blurValidator\n | typeof submitValidator,\n ) => ({ ...validator, debounceMs: 0 }) as const\n\n switch (cause) {\n case 'submit':\n return [\n noopValidator(changeValidator),\n noopValidator(blurValidator),\n submitValidator,\n ] as never\n case 'blur':\n return [blurValidator] as never\n case 'change':\n return [changeValidator] as never\n case 'server':\n default:\n return [] as never\n }\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\n/**\n * @private\n */\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\n/**\n * @private\n */\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']\n >\n >\n : never {\n const { onChange, onBlur, onSubmit, onMount } = (options.validators || {}) as\n | FieldValidators<any, any, any, any, any, any, any, any, any, any>\n | FormValidators<any, any, any, any, any, any, any, any>\n\n const changeValidator = { cause: 'change', validate: onChange } as const\n const blurValidator = { cause: 'blur', validate: onBlur } as const\n const submitValidator = { cause: 'submit', validate: onSubmit } as const\n const mountValidator = { cause: 'mount', validate: onMount } as const\n\n // Allows us to clear onServer errors\n const serverValidator = {\n cause: 'server',\n validate: () => undefined,\n } as const\n\n switch (cause) {\n case 'mount':\n return [mountValidator] as never\n case 'submit':\n return [\n changeValidator,\n blurValidator,\n submitValidator,\n serverValidator,\n ] as never\n case 'server':\n return [serverValidator] as never\n case 'blur':\n return [blurValidator, serverValidator] as never\n case 'change':\n default:\n return [changeValidator, serverValidator] as never\n }\n}\n\nexport const isGlobalFormValidationError = (\n error: unknown,\n): error is GlobalFormValidationError<unknown> => {\n return !!error && typeof error === 'object' && 'fields' in error\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false\n for (const [k, v] of objA) {\n if (!objB.has(k) || !Object.is(v, objB.get(k))) return false\n }\n return true\n }\n\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false\n for (const v of objA) {\n if (!objB.has(v)) return false\n }\n return true\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/form-core",
3
- "version": "0.42.1",
3
+ "version": "0.43.0",
4
4
  "description": "Powerful, type-safe, framework agnostic forms.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "@tanstack/store": "^0.7.0"
41
41
  },
42
42
  "devDependencies": {
43
- "arktype": "2.0.0-rc.23",
43
+ "arktype": "^2.0.0",
44
44
  "valibot": "^1.0.0-beta.9",
45
45
  "zod": "^3.24.0"
46
46
  },