form
form copied to clipboard
Server Actions example leaks backend code
Describe the bug
onServerValidate is shared between server and browser. Using the example given by the docs:
import { createFormFactory } from "@tanstack/react-form";
export const formFactory = createFormFactory({
defaultValues: {
firstName: "",
age: 0,
},
onServerValidate({ value }) {
if (value.age < 12) {
return "Server validation: You must be at least 12 to sign up";
}
},
});
https://tanstack.com/form/latest/docs/framework/react/guides/ssr
Note that it is mentioned that
Much like the
useFormhook,createFormFactoryallows you to pass defaultValues and other configuration options. A key feature here is the ability to include a property calledonServerValidate. This special validation, in contrast to client-side validations, is executed exclusively on the server when a server action is triggered.
If onServerValidate is only executed in the server, it should not be part of the JS client bundle.
Your minimal, reproducible example
https://github.com/benjavicente/tanstack-react-form-actions
Steps to reproduce
Clone the repository, build, start the server, and search for .age in JS delivered to the browser.
Expected behavior
It doesn't.
How often does this bug happen?
None
Screenshots or Videos
This is part of the JS received by the browser. Search .age<12.
;(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{2703:function(t,e,i){Promise.resolve().then(i.bind(i,3800)),Promise.resolve().then(i.bind(i,9007))},8588:function(t,e,i){"use strict";Object.defineProperty(e,"$",{enumerable:!0,get:function(){return r}});let s=i(1264);function r(t){let{createServerReference:e}=i(2366);return e(t,s.callServer)}},2328:function(t,e,i){"use strict";t.exports=i(4986)},8397:function(t,e,i){"use strict";/** * @license React * use-sync-external-store-shim.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */var s=i(4986),r="function"==typeof Object.is?Object.is:function(t,e){return t===e&&(0!==t||1/t==1/e)||t!=t&&e!=e},a=s.useState,n=s.useEffect,l=s.useLayoutEffect,o=s.useDebugValue;function u(t){var e=t.getSnapshot;t=t.value;try{var i=e();return!r(t,i)}catch(t){return!0}}var h="undefined"==typeof window||void 0===window.document||void 0===window.document.createElement?function(t,e){return e()}:function(t,e){var i=e(),s=a({inst:{value:i,getSnapshot:e}}),r=s[0].inst,h=s[1];return l(function(){r.value=i,r.getSnapshot=e,u(r)&&h({inst:r})},[t,i,e]),n(function(){return u(r)&&h({inst:r}),t(function(){u(r)&&h({inst:r})})},[t]),o(i),i};e.useSyncExternalStore=void 0!==s.useSyncExternalStore?s.useSyncExternalStore:h},4473:function(t,e,i){"use strict";/** * @license React * use-sync-external-store-shim/with-selector.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */var s=i(4986),r=i(1656),a="function"==typeof Object.is?Object.is:function(t,e){return t===e&&(0!==t||1/t==1/e)||t!=t&&e!=e},n=r.useSyncExternalStore,l=s.useRef,o=s.useEffect,u=s.useMemo,h=s.useDebugValue;e.useSyncExternalStoreWithSelector=function(t,e,i,s,r){var d=l(null);if(null===d.current){var c={hasValue:!1,value:null};d.current=c}else c=d.current;var f=n(t,(d=u(function(){function t(t){if(!o){if(o=!0,n=t,t=s(t),void 0!==r&&c.hasValue){var e=c.value;if(r(e,t))return l=e}return l=t}if(e=l,a(n,t))return e;var i=s(t);return void 0!==r&&r(e,i)?e:(n=t,l=i)}var n,l,o=!1,u=void 0===i?null:i;return[function(){return t(e())},null===u?void 0:function(){return t(u())}]},[e,i,s,r]))[0],d[1]);return o(function(){c.hasValue=!0,c.value=f},[f]),h(f),f}},1656:function(t,e,i){"use strict";t.exports=i(8397)},2432:function(t,e,i){"use strict";t.exports=i(4473)},3800:function(t,e,i){"use strict";i.d(e,{ShowScriptContent:function(){return r}});var s=i(2984);function r(){return(0,s.jsx)("code",{ref:t=>{if(console.log("element",t),t)for(let e of Array.from(document.querySelectorAll("script")))e.src&&fetch(e.src).then(t=>t.text()).then(e=>{if(e.includes("Server validation:")){var i,s;t.textContent=e;let r="Server validation: You must be at least 12 to sign up",a=e.indexOf(r),n=t.childNodes[0],l=new Range;l.setStart(n,a),l.setEnd(n,a+r.length);let o=new Highlight(l);CSS.highlights.set("danger",o);let u=document.getSelection();null==u||u.setBaseAndExtent(n,a,n,a+r.length),null==u||null===(s=u.focusNode)||void 0===s||null===(i=s.parentElement)||void 0===i||i.scrollIntoView()}})}})}},9007:function(t,e,i){"use strict";let s;i.d(e,{Form:function(){return q}});var r,a=i(9886),n=i(2984),l=i(2328),o=i(2432);function u(t,e=t=>t){return(0,o.useSyncExternalStoreWithSelector)(t.subscribe,()=>t.state,()=>t.state,e,h)}function h(t,e){if(Object.is(t,e))return!0;if("object"!=typeof t||null===t||"object"!=typeof e||null===e)return!1;let i=Object.keys(t);if(i.length!==Object.keys(e).length)return!1;for(let s=0;s<i.length;s++)if(!Object.prototype.hasOwnProperty.call(e,i[s])||!Object.is(t[i[s]],e[i[s]]))return!1;return!0}class d{constructor(t,e){this.listeners=new Set,this._batching=!1,this._flushing=0,this.subscribe=t=>{var e,i;this.listeners.add(t);let s=null==(i=null==(e=this.options)?void 0:e.onSubscribe)?void 0:i.call(e,t,this);return()=>{this.listeners.delete(t),null==s||s()}},this.setState=t=>{var e,i,s;let r=this.state;this.state=(null==(e=this.options)?void 0:e.updateFn)?this.options.updateFn(r)(t):t(r),null==(s=null==(i=this.options)?void 0:i.onUpdate)||s.call(i),this._flush()},this._flush=()=>{if(this._batching)return;let t=++this._flushing;this.listeners.forEach(e=>{this._flushing===t&&e()})},this.batch=t=>{if(this._batching)return t();this._batching=!0,t(),this._batching=!1,this._flush()},this.state=t,this.options=e}}function c(t,e){return"function"==typeof t?t(e):t}function f(t,e){return V(e).reduce((t,e)=>{if(void 0!==t)return t[e]},t)}function v(t,e,i){let s=V(e);return function t(e){if(!s.length)return c(i,e);let r=s.shift();if("string"==typeof r)return"object"==typeof e?{...e,[r]:t(e[r])}:{[r]:t()};if(Array.isArray(e)&&void 0!==r){let i=e.slice(0,r);return[...i.length?i:Array(r),t(e[r]),...e.slice(r+1)]}return[...Array(r),t()]}(t)}let p=/^(\d*)$/gm,m=/\.(\d*)\./gm,g=/^(\d*)\./gm,b=/\.(\d*$)/gm,y=/\.{2,}/gm,S="__int__",M=`${S}$1`;function V(t){if("string"!=typeof t)throw Error("Path must be a string.");return t.replaceAll("[",".").replaceAll("]","").replace(p,M).replace(m,`.${M}.`).replace(g,`${M}.`).replace(b,`.${M}`).replace(y,".").split(".").map(t=>0===t.indexOf(S)?parseInt(t.substring(S.length),10):t)}function F(t,e){let{asyncDebounceMs:i}=e,{onChangeAsync:s,onBlurAsync:r,onSubmitAsync:a,onBlurAsyncDebounceMs:n,onChangeAsyncDebounceMs:l}=e.validators||{},o=i??0,u={cause:"change",validate:s,debounceMs:l??o},h={cause:"blur",validate:r,debounceMs:n??o},d=t=>({...t,debounceMs:0});switch(t){case"submit":return[d(u),d(h),{cause:"submit",validate:a,debounceMs:0}];case"blur":return[h];case"change":return[u];default:return[]}}function A(t,e){let{onChange:i,onBlur:s,onSubmit:r}=e.validators||{},a={cause:"change",validate:i},n={cause:"blur",validate:s},l={cause:"server",validate:()=>void 0};switch(t){case"submit":return[a,n,{cause:"submit",validate:r},l];case"server":return[l];case"blur":return[n,l];default:return[a,l]}}class w{constructor(t){this.options={},this.mount=()=>{this.getInfo().instance=this;let t=this.form.store.subscribe(()=>{this.store.batch(()=>{let t=this.getValue(),e=this.getMeta();t!==this.state.value&&this.store.setState(e=>({...e,value:t})),e!==this.state.meta&&this.store.setState(t=>({...t,meta:e}))})});this.update(this.options);let{onMount:e}=this.options.validators||{};if(e){let t=this.runValidator({validate:e,value:{value:this.state.value,fieldApi:this},type:"validate"});t&&this.setMeta(e=>({...e,errorMap:{...null==e?void 0:e.errorMap,onMount:t}}))}return()=>{let e=this.options.preserveValue;t(),e||this.form.deleteField(this.name)}},this.update=t=>{if(void 0===this.state.value){let e=f(t.form.options.defaultValues,t.name);void 0!==t.defaultValue?this.setValue(t.defaultValue):void 0!==e&&this.setValue(e)}void 0===this._getMeta()&&this.setMeta(this.state.meta),this.options=t},this.getValue=()=>this.form.getFieldValue(this.name),this.setValue=(t,e)=>{this.form.setFieldValue(this.name,t,e),this.validate("change")},this._getMeta=()=>this.form.getFieldMeta(this.name),this.getMeta=()=>this._getMeta()??{isValidating:!1,isTouched:!1,isDirty:!1,isPristine:!0,touchedErrors:[],errors:[],errorMap:{},...this.options.defaultMeta},this.setMeta=t=>this.form.setFieldMeta(this.name,t),this.getInfo=()=>this.form.getFieldInfo(this.name),this.pushValue=t=>this.form.pushFieldValue(this.name,t),this.insertValue=(t,e)=>this.form.insertFieldValue(this.name,t,e),this.removeValue=t=>this.form.removeFieldValue(this.name,t),this.swapValues=(t,e)=>this.form.swapFieldValues(this.name,t,e),this.getLinkedFields=t=>{let e=Object.values(this.form.fieldInfo),i=[];for(let s of e){if(!s.instance)continue;let{onChangeListenTo:e,onBlurListenTo:r}=s.instance.options.validators||{};"change"===t&&(null==e?void 0:e.includes(this.name))&&i.push(s.instance),"blur"===t&&(null==r?void 0:r.includes(this.name))&&i.push(s.instance)}return i},this.moveValue=(t,e)=>this.form.moveFieldValues(this.name,t,e),this.validateSync=t=>{let e=A(t,this.options),i=this.getLinkedFields(t).reduce((e,i)=>{let s=A(t,i.options);return s.forEach(t=>{t.field=i}),e.concat(s)},[]),s=!1;this.form.store.batch(()=>{let t=(t,e)=>{let i=$(t.runValidator({validate:e.validate,value:{value:t.getValue(),fieldApi:t},type:"validate"})),r=j(e.cause);t.state.meta.errorMap[r]!==i&&t.setMeta(t=>({...t,errorMap:{...t.errorMap,[j(e.cause)]:i}})),i&&(s=!0)};for(let i of e)i.validate&&t(this,i);for(let e of i)e.validate&&t(e.field,e)});let r=j("submit");return this.state.meta.errorMap[r]&&"submit"!==t&&!s&&this.setMeta(t=>({...t,errorMap:{...t.errorMap,[r]:void 0}})),{hasErrored:s}},this.validateAsync=async t=>{let e=F(t,this.options),i=this.getLinkedFields(t),s=i.reduce((e,i)=>{let s=F(t,i.options);return s.forEach(t=>{t.field=i}),e.concat(s)},[]);for(let t of(this.state.meta.isValidating||this.setMeta(t=>({...t,isValidating:!0})),i))t.setMeta(t=>({...t,isValidating:!0}));let r=[],a=[],n=(e,i,s)=>{let r=j(i.cause),a=e.getInfo().validationMetaMap[r];null==a||a.lastAbortController.abort();let n=new AbortController;this.getInfo().validationMetaMap[r]={lastAbortController:n},s.push(new Promise(async s=>{let r;try{r=await new Promise((t,s)=>{setTimeout(async()=>{if(n.signal.aborted)return t(void 0);try{t(await this.runValidator({validate:i.validate,value:{value:e.getValue(),fieldApi:e,signal:n.signal},type:"validateAsync"}))}catch(t){s(t)}},i.debounceMs)})}catch(t){r=t}let a=$(r);e.setMeta(e=>({...e,errorMap:{...null==e?void 0:e.errorMap,[j(t)]:a}})),s(a)}))};for(let t of e)t.validate&&n(this,t,r);for(let t of s)t.validate&&n(t.field,t,a);let l=[];for(let t of((r.length||a.length)&&(l=await Promise.all(r),await Promise.all(a)),this.setMeta(t=>({...t,isValidating:!1})),i))t.setMeta(t=>({...t,isValidating:!1}));return l.filter(Boolean)},this.validate=t=>{if(!this.state.meta.isTouched)return[];try{this.form.validate(t)}catch(t){}let{hasErrored:e}=this.validateSync(t);return e&&!this.options.asyncAlways?this.state.meta.errors:this.validateAsync(t)},this.handleChange=t=>{this.setValue(t,{touch:!0})},this.handleBlur=()=>{this.state.meta.isTouched||(this.setMeta(t=>({...t,isTouched:!0})),this.validate("change")),this.validate("blur")},this.form=t.form,this.name=t.name,void 0!==t.defaultValue&&this.form.setFieldValue(this.name,t.defaultValue),this.store=new d({value:this.getValue(),meta:this._getMeta()??{isValidating:!1,isTouched:!1,isDirty:!1,isPristine:!0,touchedErrors:[],errors:[],errorMap:{},...t.defaultMeta}},{onUpdate:()=>{let t=this.store.state;t.meta.errors=Object.values(t.meta.errorMap).filter(t=>void 0!==t),t.meta.touchedErrors=t.meta.isTouched?t.meta.errors:[],t.meta.isPristine=!t.meta.isDirty,this.prevState=t,this.state=t}}),this.state=this.store.state,this.prevState=this.state,this.options=t}runValidator(t){for(let e of[this.form.options.validatorAdapter,this.options.validatorAdapter])if(e&&"function"!=typeof t.validate)return e()[t.type](t.value,t.validate);return t.validate(t.value)}}function $(t){if(t)return"string"!=typeof t?"Invalid Form Values":t}function j(t){switch(t){case"submit":return"onSubmit";case"blur":return"onBlur";case"mount":return"onMount";case"server":return"onServer";default:return"onChange"}}let E="undefined"!=typeof window?l.useLayoutEffect:l.useEffect;function T(t){let[e]=(0,l.useState)(()=>{let e=new w({...t,form:t.form,name:t.name});return e.Field=O,e});return E(e.mount,[e]),E(()=>{e.update(t)}),u(e.store,"array"===t.mode?t=>[t.meta,Object.keys(t.value).length]:void 0),e}function O({children:t,...e}){let i=T(e);return(0,n.jsx)(n.Fragment,{children:c(t,i)})}function _(t){return{values:t.values??{},errors:t.errors??[],errorMap:t.errorMap??{},fieldMeta:t.fieldMeta??{},canSubmit:t.canSubmit??!0,isFieldsValid:t.isFieldsValid??!1,isFieldsValidating:t.isFieldsValidating??!1,isFormValid:t.isFormValid??!1,isFormValidating:t.isFormValidating??!1,isSubmitted:t.isSubmitted??!1,isSubmitting:t.isSubmitting??!1,isTouched:t.isTouched??!1,isPristine:t.isPristine??!0,isDirty:t.isDirty??!1,isValid:t.isValid??!1,isValidating:t.isValidating??!1,submissionAttempts:t.submissionAttempts??0,validationMetaMap:t.validationMetaMap??{onChange:void 0,onBlur:void 0,onSubmit:void 0,onMount:void 0,onServer:void 0}}}class P{constructor(t){var e;this.options={},this.fieldInfo={},this.prevTransformArray=[],this.mount=()=>{let{onMount:t}=this.options.validators||{};if(!t)return;let e=this.runValidator({validate:t,value:{value:this.state.values,formApi:this},type:"validate"});e&&this.store.setState(t=>({...t,errorMap:{...t.errorMap,onMount:e}}))},this.update=t=>{if(!t)return;let e=this.options;this.options=t,this.store.batch(()=>{let i=t.defaultValues&&t.defaultValues!==e.defaultValues&&!this.state.isTouched,s=t.defaultState!==e.defaultState&&!this.state.isTouched;this.store.setState(()=>_(Object.assign({},this.state,s?t.defaultState:{},i?{values:t.defaultValues}:{})))})},this.reset=()=>{let{fieldMeta:t}=this.state,e=this.resetFieldMeta(t);this.store.setState(()=>{var t;return _({...this.options.defaultState,values:this.options.defaultValues??(null==(t=this.options.defaultState)?void 0:t.values),fieldMeta:e})})},this.validateAllFields=async t=>{let e=[];return this.store.batch(()=>{Object.values(this.fieldInfo).forEach(i=>{if(!i.instance)return;let s=i.instance;e.push(Promise.resolve().then(()=>s.validate(t))),i.instance.state.meta.isTouched||i.instance.setMeta(t=>({...t,isTouched:!0}))})}),(await Promise.all(e)).flat()},this.validateSync=t=>{let e=A(t,this.options),i=!1;this.store.batch(()=>{for(let t of e){if(!t.validate)continue;let e=I(this.runValidator({validate:t.validate,value:{value:this.state.values,formApi:this},type:"validate"})),s=x(t.cause);this.state.errorMap[s]!==e&&this.store.setState(t=>({...t,errorMap:{...t.errorMap,[s]:e}})),e&&(i=!0)}});let s=x("submit");return this.state.errorMap[s]&&"submit"!==t&&!i&&this.store.setState(t=>({...t,errorMap:{...t.errorMap,[s]:void 0}})),{hasErrored:i}},this.validateAsync=async t=>{let e=F(t,this.options);this.state.isFormValidating||this.store.setState(t=>({...t,isFormValidating:!0}));let i=[];for(let s of e){if(!s.validate)continue;let e=x(s.cause),r=this.state.validationMetaMap[e];null==r||r.lastAbortController.abort();let a=new AbortController;this.state.validationMetaMap[e]={lastAbortController:a},i.push(new Promise(async e=>{let i;try{i=await new Promise((t,e)=>{setTimeout(async()=>{if(a.signal.aborted)return t(void 0);try{t(await this.runValidator({validate:s.validate,value:{value:this.state.values,formApi:this,signal:a.signal},type:"validateAsync"}))}catch(t){e(t)}},s.debounceMs)})}catch(t){i=t}let r=I(i);this.store.setState(e=>({...e,errorMap:{...e.errorMap,[x(t)]:r}})),e(r)}))}let s=[];return i.length&&(s=await Promise.all(i)),this.store.setState(t=>({...t,isFormValidating:!1})),s.filter(Boolean)},this.validate=t=>{let{hasErrored:e}=this.validateSync(t);return e&&!this.options.asyncAlways?this.state.errors:this.validateAsync(t)},this.handleSubmit=async()=>{var t,e,i,s,r,a;if(this.store.setState(t=>({...t,isSubmitted:!1,submissionAttempts:t.submissionAttempts+1})),!this.state.canSubmit)return;this.store.setState(t=>({...t,isSubmitting:!0}));let n=()=>{this.store.setState(t=>({...t,isSubmitting:!1}))};if(await this.validateAllFields("submit"),!this.state.isFieldsValid){n(),null==(e=(t=this.options).onSubmitInvalid)||e.call(t,{value:this.state.values,formApi:this});return}if(await this.validate("submit"),!this.state.isValid){n(),null==(s=(i=this.options).onSubmitInvalid)||s.call(i,{value:this.state.values,formApi:this});return}try{await (null==(a=(r=this.options).onSubmit)?void 0:a.call(r,{value:this.state.values,formApi:this})),this.store.batch(()=>{this.store.setState(t=>({...t,isSubmitted:!0})),n()})}catch(t){throw n(),t}},this.getFieldValue=t=>f(this.state.values,t),this.getFieldMeta=t=>this.state.fieldMeta[t],this.getFieldInfo=t=>{var e;return(e=this.fieldInfo)[t]||(e[t]={instance:null,validationMetaMap:{onChange:void 0,onBlur:void 0,onSubmit:void 0,onMount:void 0,onServer:void 0}})},this.setFieldMeta=(t,e)=>{this.store.setState(i=>({...i,fieldMeta:{...i.fieldMeta,[t]:c(e,i.fieldMeta[t])}}))},this.resetFieldMeta=t=>Object.keys(t).reduce((t,e)=>(t[e]={isValidating:!1,isTouched:!1,isDirty:!1,isPristine:!0,touchedErrors:[],errors:[],errorMap:{}},t),{}),this.setFieldValue=(t,e,i)=>{let s=null==i?void 0:i.touch;this.store.batch(()=>{s&&this.setFieldMeta(t,t=>({...t,isTouched:!0,isDirty:!0})),this.store.setState(i=>({...i,values:v(i.values,t,e)}))})},this.deleteField=t=>{this.store.setState(e=>{let i={...e};return i.values=function(t,e){let i=V(e);return function t(e){if(!e)return;if(1===i.length){let t=i[0];if(Array.isArray(e)&&"number"==typeof t)return e.filter((e,i)=>i!==t);let{[t]:s,...r}=e;return r}let s=i.shift();if("string"==typeof s&&"object"==typeof e)return{...e,[s]:t(e[s])};if("number"==typeof s&&Array.isArray(e)){if(s>=e.length)return e;let i=e.slice(0,s);return[...i.length?i:Array(s),t(e[s]),...e.slice(s+1)]}throw Error("It seems we have created an infinite loop in deleteBy. ")}(t)}(i.values,t),delete i.fieldMeta[t],i}),delete this.fieldInfo[t]},this.pushFieldValue=(t,e,i)=>this.setFieldValue(t,t=>[...Array.isArray(t)?t:[],e],i),this.insertFieldValue=(t,e,i,s)=>{this.setFieldValue(t,t=>t.map((t,s)=>s===e?i:t),s)},this.removeFieldValue=(t,e,i)=>{this.setFieldValue(t,t=>t.filter((t,i)=>i!==e),i)},this.swapFieldValues=(t,e,i)=>{this.setFieldValue(t,t=>{let s=t[e],r=t[i];return v(v(t,`${e}`,r),`${i}`,s)})},this.moveFieldValues=(t,e,i)=>{this.setFieldValue(t,t=>(t.splice(i,0,t.splice(e,1)[0]),t))},this.store=new d(_({...null==t?void 0:t.defaultState,values:(null==t?void 0:t.defaultValues)??(null==(e=null==t?void 0:t.defaultState)?void 0:e.values),isFormValid:!0}),{onUpdate:()=>{var t,e;let{state:i}=this.store,s=Object.values(i.fieldMeta),r=s.some(t=>null==t?void 0:t.isValidating),a=!s.some(t=>{var e;return(null==t?void 0:t.errorMap)&&!(Array.isArray(e=Object.values(t.errorMap).filter(Boolean))&&0===e.length)}),n=s.some(t=>null==t?void 0:t.isTouched),l=s.some(t=>null==t?void 0:t.isDirty),o=r||i.isFormValidating;i.errors=Object.values(i.errorMap).filter(t=>void 0!==t);let u=0===i.errors.length,h=a&&u,d=0===i.submissionAttempts&&!n||!o&&!i.isSubmitting&&h;i={...i,isFieldsValidating:r,isFieldsValid:a,isFormValid:u,isValid:h,canSubmit:d,isTouched:n,isPristine:!l,isDirty:l},this.state=i,this.store.state=this.state;let c=(null==(t=this.options.transform)?void 0:t.deps)??[];(c.length!==this.prevTransformArray.length||c.some((t,e)=>t!==this.prevTransformArray[e]))&&(null==(e=this.options.transform)||e.fn(this),this.store.state=this.state,this.prevTransformArray=c)}}),this.state=this.store.state,this.update(t||{})}runValidator(t){let e=this.options.validatorAdapter;return e&&"function"!=typeof t.validate?e()[t.type](t.value,t.validate):t.validate(t.value)}}function I(t){if(t)return"string"!=typeof t?"Invalid Form Values":t}function x(t){switch(t){case"submit":return"onSubmit";case"blur":return"onBlur";case"mount":return"onMount";case"server":return"onServer";default:return"onChange"}}var C=/^\d+$/u,D=/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])$/u,k=/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])T(?:0\d|1\d|2[0-3]):[0-5]\d$/u,B=/^(?:0\d|1\d|2[0-3]):[0-5]\d$/u,N=/^(?:0\d|1\d|2[0-3])(?::[0-5]\d){2}$/u,L=/^\d{4}-W(?:0[1-9]|[1-4]\d|5[0-3])$/u;function Z(t){if(!t)return null;if(D.test(t))return new Date(`${t}T00:00:00.000Z`);if(k.test(t))return new Date(`${t}:00.000Z`);if(L.test(t)){let[e,i]=t.split("-W"),s=new Date(`${e}-01-01T00:00:00.000Z`);return s.setUTCDate((+i-1)*7+1),s}return new Date(B.test(t)?`1970-01-01T${t}:00.000Z`:N.test(t)?`1970-01-01T${t}.000Z`:C.test(t)?+t:t)}function U(t,e,i){return t.reduce((t,i,s)=>t[i]=t[i]||("$"===e[s+1]?[]:{}),i)}function W(t,e){let i=[];if(t.includes(".$.")){let s=(t,r)=>{let[a,...n]=t.split(".$."),l=r?`${r}.${a}`:a,o=U(l.split("."),t.split("."),e);for(let t=0;t<o.length;t++){let e=`${l}.${t}`;n.length>1?s(n.join(".$."),e):i.push(`${e}.${n[0]}`)}};s(t)}else i.push(t);return i}let R={useForm:t=>(function(t){let[e]=(0,l.useState)(()=>{let e=new P(t);return e.Field=function(t){return(0,n.jsx)(O,{...t,form:e})},e.useField=t=>T({...t,form:e}),e.useStore=t=>u(e.store,t),e.Subscribe=t=>c(t.children,u(e.store,t.selector)),e});return E(e.mount,[]),e.useStore(t=>t.isSubmitting),E(()=>{e.update(t)}),e})(Object.assign({},r,t)),useField:T,Field:O,validateFormData:(s=r={defaultValues:{firstName:"",age:0},onServerValidate(t){let{value:e}=t;if(e.age<12)return"Server validation: You must be at least 12 to sign up"}},async(t,e)=>{var i;let{validatorAdapter:r,onServerValidate:a}=s||{},n=(i={value:function(t,e){let i={};for(let[s,r]of t.entries()){let t=s.replace(/.\d+./g,".$."),a=t.split(".");s.split(".").reduce((i,s,n,l)=>{if(n<l.length-1){if(i[s])return i[s];let t=n<l.length-2?"$"===a[n+1]:e?.arrays?.includes(a.slice(0,-1).join("."));return i[s]=t?[]:{}}(!e?.files?.includes(t)||r&&("string"==typeof r||r.size))&&(i[s]=function(t,e,i){if(t?.booleans?.includes(e))return"false"!==i&&"0"!==i;if("string"==typeof i){if(t?.dates?.includes(e))return Z(i);if(t?.numbers?.includes(e))return/^-?\d*(\.\d+)?$/.test(i)?parseFloat(i):Z(i).getTime()}return i}(e,t,r))},i)}if(e?.arrays)for(let t of e.arrays)for(let e of W(t,i)){let s=e.split("."),r=s[s.length-1],a=U(s.slice(0,-1),t.split("."),i);a[r]||(a[r]=[])}if(e?.booleans)for(let t of e.booleans)for(let e of W(t,i)){let s=e.split("."),r=s[s.length-1],a=U(s.slice(0,-1),t.split("."),i);!0!==a[r]&&(a[r]=!1)}return i}(t,e)},r&&"function"!=typeof a?r().validate(i,a):a(i));return{errorMap:{onServer:n},errors:n?[n]:[]}}),initialFormState:{errorMap:{onServer:void 0},errors:[]}};i(1264);var Y=(0,i(8588).$)("def8069cb35f2a7ce5c0b74936f11003541b4c77");function q(){let[t,e]=(0,a.useFormState)(Y,R.initialFormState),{useStore:i,Subscribe:s,handleSubmit:r,Field:n}=R.useForm({transform:{fn:e=>((function t(e,i){for(let s of new Set([...Object.keys(e),...Object.keys(i)]))if(Array.isArray(e[s])&&Array.isArray(i[s]))e[s]=[...e[s],...i[s]];else if("object"==typeof e[s]&&"object"==typeof i[s])t(e[s],i[s]);else{if(!(s in i)&&void 0===i[s])continue;e[s]=i[s]}return e})(e.state,t),e),deps:[t]}});return i(t=>t.errors),null}}},function(t){t.O(0,[645,563,744],function(){return t(t.s=2703)}),_N_E=t.O()}]);;
Platform
MacOS.
TanStack Form adapter
react-form
TanStack Form version
0.19.5
TypeScript version
No response
Additional context
I would mark the SSR with Next section in the docs with a warning. Also, the form factory doesn't feel like the right primitive to share code between server and client.
A server only layer could be useful to provide a type-safe way to parse, validate and server validate the form, to then respond with an updated form or another result 🤔