@@ -4,10 +4,12 @@ import {
44import  isEqual  from  "lodash.isequal" ; 
55import  {  useQuery  }  from  "@tanstack/react-query" ; 
66import  type  { 
7-   ComponentReloadPropsOpts ,  ConfigurableProp ,  ConfigurableProps ,  ConfiguredProps ,  V1Component , 
7+   ComponentReloadPropsOpts ,  ConfigurableProp ,  ConfigurableProps ,  ConfiguredProps ,  V1Component ,   PropValue , 
88}  from  "@pipedream/sdk" ; 
99import  {  useFrontendClient  }  from  "./frontend-client-context" ; 
1010import  type  {  ComponentFormProps  }  from  "../components/ComponentForm" ; 
11+ import  type  {  FormFieldContext  }  from  "./form-field-context" ; 
12+ import  {  appPropError  }  from  "./use-app" ; 
1113
1214export  type  DynamicProps < T  extends  ConfigurableProps >  =  {  id : string ;  configurableProps : T ;  } ;  // TODO 
1315
@@ -17,12 +19,15 @@ export type FormContext<T extends ConfigurableProps> = {
1719  configuredProps : ConfiguredProps < T > ; 
1820  dynamicProps ?: DynamicProps < T > ;  // lots of calls require dynamicProps?.id, so need to expose 
1921  dynamicPropsQueryIsFetching ?: boolean ; 
22+   fields : Record < string ,  FormFieldContext < ConfigurableProp > > ; 
2023  id : string ; 
2124  isValid : boolean ; 
2225  optionalPropIsEnabled : ( prop : ConfigurableProp )  =>  boolean ; 
2326  optionalPropSetEnabled : ( prop : ConfigurableProp ,  enabled : boolean )  =>  void ; 
2427  props : ComponentFormProps < T > ; 
28+   propsNeedConfiguring : string [ ] ; 
2529  queryDisabledIdx ?: number ; 
30+   registerField : < T  extends  ConfigurableProp > ( field : FormFieldContext < T > )  =>  void ; 
2631  setConfiguredProp : ( idx : number ,  value : unknown )  =>  void ;  // XXX type safety for value (T will rarely be static right?) 
2732  setSubmitting : ( submitting : boolean )  =>  void ; 
2833  submitting : boolean ; 
@@ -64,6 +69,10 @@ export const FormContextProvider = <T extends ConfigurableProps>({
6469    queryDisabledIdx , 
6570    setQueryDisabledIdx , 
6671  ]  =  useState < number  |  undefined > ( 0 ) ; 
72+   const  [ 
73+     fields , 
74+     setFields , 
75+   ]  =  useState < Record < string ,  FormFieldContext < ConfigurableProp > > > ( { } ) ; 
6776  const  [ 
6877    submitting , 
6978    setSubmitting , 
@@ -129,6 +138,16 @@ export const FormContextProvider = <T extends ConfigurableProps>({
129138    enabled : reloadPropIdx  !=  null ,  // TODO or props.dynamicPropsId && !dynamicProps 
130139  } ) ; 
131140
141+   const  [ 
142+     propsNeedConfiguring , 
143+     setPropsNeedConfiguring , 
144+   ]  =  useState < string [ ] > ( [ ] ) ; 
145+   useEffect ( ( )  =>  { 
146+     checkPropsNeedConfiguring ( ) 
147+   } ,  [ 
148+     configuredProps , 
149+   ] ) ; 
150+ 
132151  // XXX fix types of dynamicProps, props.component so this type decl not needed 
133152  let  configurableProps : T  =  dynamicProps ?. configurableProps  ||  formProps . component . configurable_props  ||  [ ] ; 
134153  if  ( propNames ?. length )  { 
@@ -147,7 +166,7 @@ export const FormContextProvider = <T extends ConfigurableProps>({
147166
148167  // these validations are necessary because they might override PropInput for number case for instance 
149168  // so can't rely on that base control form validation 
150-   const  propErrors  =  ( prop : ConfigurableProp ,  value : unknown ) : string [ ]  =>  { 
169+   const  propErrors  =  < T   extends   ConfigurableProps > ( prop : ConfigurableProp ,  value : unknown ) : string [ ]  =>  { 
151170    const  errs : string [ ]  =  [ ] ; 
152171    if  ( value  ===  undefined )  { 
153172      if  ( ! prop . optional )  { 
@@ -173,7 +192,14 @@ export const FormContextProvider = <T extends ConfigurableProps>({
173192        errs . push ( "not a string" ) ; 
174193      } 
175194    }  else  if  ( prop . type  ===  "app" )  { 
176-       // TODO need to know about auth type 
195+       const  field  =  fields [ prop . name ] 
196+       if  ( field )  { 
197+         const  app  =  field . extra . app 
198+         const  err  =  appPropError ( {  value,  app } ) 
199+         if  ( err )  errs . push ( err ) 
200+       }  else  { 
201+         errs . push ( "field not registered" ) 
202+       } 
177203    } 
178204    return  errs ; 
179205  } ; 
@@ -302,6 +328,27 @@ export const FormContextProvider = <T extends ConfigurableProps>({
302328    setEnabledOptionalProps ( newEnabledOptionalProps ) ; 
303329  } ; 
304330
331+   const  checkPropsNeedConfiguring  =  ( )  =>  { 
332+     const  _propsNeedConfiguring  =  [ ] 
333+     for  ( const  prop  of  configurableProps )  { 
334+       if  ( ! prop  ||  prop . optional  ||  prop . hidden )  continue 
335+       const  value  =  configuredProps [ prop . name  as  keyof  ConfiguredProps < T > ] 
336+       const  errors  =  propErrors ( prop ,  value ) 
337+       if  ( errors . length )  { 
338+         _propsNeedConfiguring . push ( prop . name ) 
339+       } 
340+     } 
341+     // propsNeedConfiguring.splice(0, propsNeedConfiguring.length, ..._propsNeedConfiguring) 
342+     setPropsNeedConfiguring ( _propsNeedConfiguring ) 
343+   } 
344+ 
345+   const  registerField  =  < T  extends  ConfigurableProp > ( field : FormFieldContext < T > )  =>  { 
346+     setFields ( ( fields )  =>  { 
347+       fields [ field . prop . name ]  =  field 
348+       return  fields 
349+     } ) ; 
350+   } ; 
351+ 
305352  // console.log("***", configurableProps, configuredProps) 
306353  const  value : FormContext < T >  =  { 
307354    id, 
@@ -313,9 +360,12 @@ export const FormContextProvider = <T extends ConfigurableProps>({
313360    configuredProps, 
314361    dynamicProps, 
315362    dynamicPropsQueryIsFetching, 
363+     fields, 
316364    optionalPropIsEnabled, 
317365    optionalPropSetEnabled, 
366+     propsNeedConfiguring, 
318367    queryDisabledIdx, 
368+     registerField, 
319369    setConfiguredProp, 
320370    setSubmitting, 
321371    submitting, 
0 commit comments