* Get a feature value with a default fallback - blocks until initialized. * @internal Used by both deprecated and cached functions.
( feature: string, defaultValue: T, logExposure: boolean, )
| 668 | * @internal Used by both deprecated and cached functions. |
| 669 | */ |
| 670 | async function getFeatureValueInternal<T>( |
| 671 | feature: string, |
| 672 | defaultValue: T, |
| 673 | logExposure: boolean, |
| 674 | ): Promise<T> { |
| 675 | // Check env var overrides first (for eval harnesses) |
| 676 | const overrides = getEnvOverrides() |
| 677 | if (overrides && feature in overrides) { |
| 678 | return overrides[feature] as T |
| 679 | } |
| 680 | const configOverrides = getConfigOverrides() |
| 681 | if (configOverrides && feature in configOverrides) { |
| 682 | return configOverrides[feature] as T |
| 683 | } |
| 684 | |
| 685 | if (!isGrowthBookEnabled()) { |
| 686 | return defaultValue |
| 687 | } |
| 688 | |
| 689 | const growthBookClient = await initializeGrowthBook() |
| 690 | if (!growthBookClient) { |
| 691 | return defaultValue |
| 692 | } |
| 693 | |
| 694 | // Use cached remote eval values if available (workaround for SDK bug) |
| 695 | let result: T |
| 696 | if (remoteEvalFeatureValues.has(feature)) { |
| 697 | result = remoteEvalFeatureValues.get(feature) as T |
| 698 | } else { |
| 699 | result = growthBookClient.getFeatureValue(feature, defaultValue) as T |
| 700 | } |
| 701 | |
| 702 | // Log experiment exposure using stored experiment data |
| 703 | if (logExposure) { |
| 704 | logExposureForFeature(feature) |
| 705 | } |
| 706 | |
| 707 | if (process.env.USER_TYPE === 'ant') { |
| 708 | logForDebugging( |
| 709 | `GrowthBook: getFeatureValue("${feature}") = ${jsonStringify(result)}`, |
| 710 | ) |
| 711 | } |
| 712 | return result |
| 713 | } |
| 714 | |
| 715 | /** |
| 716 | * @deprecated Use getFeatureValue_CACHED_MAY_BE_STALE instead, which is non-blocking. |
no test coverage detected