@@ -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