import { isAttributeFunction , isDerivedFunction , isFactoryFunction , isArrayFactoryFunction , } from "./utils" ; import { Config } from "./define" ; import { getConfig } from "./config" ; function compute < Key extends keyof Result , Values extends Config < Result > , Result > ( key , values , result , invocations , path , override , computedKeys ) { if ( computedKeys . indexOf ( key ) >= 0 ) { return ; } const value = values [ key ] ; if ( isDerivedFunction < Result , Result [ Key ] > ( value ) ) { result [ key ] = value ( result , values , invocations , path , override , computedKeys ) ; } else if ( isFactoryFunction < Result [ Key ] > ( value ) ) { result [ key ] = value ( ) ; } else if ( isArrayFactoryFunction < Result [ Key ] > ( value ) ) { result [ key ] = value ( ) ; } else if ( isAttributeFunction < Result [ Key ] > ( value ) ) { result [ key ] = value ( invocations ) ; } else { if ( ! ( key in override ) ) { warnAboutHardCodedValues ( key , value ) ; } result [ key ] = value as Result [ Key ] ; } computedKeys . push ( key ) ; } /**
 * Explicitly setting an object or array as a value in a factory can lead to
 * really challenging and subtle bugs since they will be shared across all
 * instances of a factory. Check for objects and arrays and by default display
 * a warning.
 */ const warnAboutHardCodedValues = < Key , Value > ( key , value ) => { let message ; if ( Array . isArray ( value ) ) { message = `\`${ key }\` contains a hard-coded array.` ; } else if ( typeof value === "object" && value !== null ) { message = `\`${ key }\` contains a hard-coded object.` ; } const { errorOnHardCodedValues } = getConfig ( ) ; if ( message ) { message += ` It will be shared across all instances of this factory. Consider using a factory function.` ; if ( errorOnHardCodedValues ) { console . trace ( ) ; throw message ; } else { console . warn ( message ) ; } } } ; export { compute } ;