form icon indicating copy to clipboard operation
form copied to clipboard

Server Actions example leaks backend code

Open benjavicente opened this issue 1 year ago • 0 comments

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 useForm hook, createFormFactory allows you to pass defaultValues and other configuration options. A key feature here is the ability to include a property called onServerValidate. 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 🤔

benjavicente avatar May 17 '24 22:05 benjavicente