@@ -108,7 +108,6 @@ export class BucketClient {
108108 refetchInterval : number ;
109109 staleWarningInterval : number ;
110110 headers : Record < string , string > ;
111- fallbackFeatures ?: Record < keyof TypedFeatures , RawFeature > ;
112111 featureOverrides : FeatureOverridesFn ;
113112 offline : boolean ;
114113 fetchFeatures : boolean ;
@@ -143,7 +142,6 @@ export class BucketClient {
143142 * @param options.httpClient - The HTTP client to use for sending requests (optional).
144143 * @param options.logLevel - The log level to use for logging (optional).
145144 * @param options.offline - Whether to run in offline mode (optional).
146- * @param options.fallbackFeatures - The fallback features to use if the feature is not found (optional).
147145 * @param options.batchOptions - The options for the batch buffer (optional).
148146 * @param options.featureOverrides - The feature overrides to use for the client (optional).
149147 * @param options.configFile - The path to the config file (optional).
@@ -173,12 +171,6 @@ export class BucketClient {
173171 options . httpClient === undefined || isObject ( options . httpClient ) ,
174172 "httpClient must be an object" ,
175173 ) ;
176- ok (
177- options . fallbackFeatures === undefined ||
178- Array . isArray ( options . fallbackFeatures ) ||
179- isObject ( options . fallbackFeatures ) ,
180- "fallbackFeatures must be an array or object" ,
181- ) ;
182174 ok (
183175 options . batchOptions === undefined || isObject ( options . batchOptions ) ,
184176 "batchOptions must be an object" ,
@@ -214,42 +206,6 @@ export class BucketClient {
214206 options . logLevel ?? config ?. logLevel ?? "INFO" ,
215207 ) ;
216208
217- // todo: deprecate fallback features in favour of a more operationally
218- // friendly way of setting fall backs.
219- const fallbackFeatures = Array . isArray ( options . fallbackFeatures )
220- ? options . fallbackFeatures . reduce (
221- ( acc , key ) => {
222- acc [ key as keyof TypedFeatures ] = {
223- isEnabled : true ,
224- key,
225- } ;
226- return acc ;
227- } ,
228- { } as Record < keyof TypedFeatures , RawFeature > ,
229- )
230- : isObject ( options . fallbackFeatures )
231- ? Object . entries ( options . fallbackFeatures ) . reduce (
232- ( acc , [ key , fallback ] ) => {
233- acc [ key as keyof TypedFeatures ] = {
234- isEnabled :
235- typeof fallback === "object"
236- ? fallback . isEnabled
237- : ! ! fallback ,
238- key,
239- config :
240- typeof fallback === "object" && fallback . config
241- ? {
242- key : fallback . config . key ,
243- payload : fallback . config . payload ,
244- }
245- : undefined ,
246- } ;
247- return acc ;
248- } ,
249- { } as Record < keyof TypedFeatures , RawFeature > ,
250- )
251- : undefined ;
252-
253209 this . rateLimiter = newRateLimiter (
254210 FEATURE_EVENT_RATE_LIMITER_WINDOW_SIZE_MS ,
255211 ) ;
@@ -271,7 +227,6 @@ export class BucketClient {
271227 refetchInterval : FEATURES_REFETCH_MS ,
272228 fetchFeatures : options . fetchFeatures ?? true ,
273229 staleWarningInterval : FEATURES_REFETCH_MS * 5 ,
274- fallbackFeatures : fallbackFeatures ,
275230 featureOverrides :
276231 typeof config . featureOverrides === "function"
277232 ? config . featureOverrides
@@ -300,6 +255,13 @@ export class BucketClient {
300255 return res ;
301256 } ,
302257 ) ;
258+
259+ if ( this . _config . offline ) {
260+ this . logger . info ( "running in offline mode" ) ;
261+ this . featuresCache . set ( {
262+ features : [ ] ,
263+ } ) ;
264+ }
303265 }
304266
305267 /**
@@ -475,7 +437,7 @@ export class BucketClient {
475437 **/
476438 public bootstrapFeatureDefinitions ( features : FeaturesAPIResponse ) {
477439 this . featuresCache . set ( features ) ;
478- this . logger . info ( "Bootstrapped feature definitions") ;
440+ this . logger . debug ( "bootstrapped feature definitions") ;
479441 }
480442
481443 /**
@@ -936,23 +898,16 @@ export class BucketClient {
936898 checkContextWithTracking ( options ) ;
937899
938900 void this . syncContext ( options ) ;
939- let featureDefinitions : FeaturesAPIResponse [ "features" ] ;
940901
941- if ( this . _config . offline ) {
942- featureDefinitions = [ ] ;
943- } else {
944- const fetchedFeatures = this . featuresCache . get ( ) ;
945- if ( ! fetchedFeatures ) {
946- this . logger . warn (
947- "failed to use feature definitions, there are none cached yet. Using fallback features." ,
948- ) ;
949- return this . _config . fallbackFeatures || { } ;
950- }
951-
952- featureDefinitions = fetchedFeatures . features ;
902+ const featureDefinitions = this . featuresCache . get ( ) ;
903+ if ( ! featureDefinitions ) {
904+ this . logger . warn (
905+ "No feature definitions available. `getFeatures` will return empty and `getFeature(key)` will have `isEnabled: false`. Did you forget to call `initialize()`?" ,
906+ ) ;
907+ return { } ;
953908 }
954-
955- const featureMap = featureDefinitions . reduce (
909+ const features = featureDefinitions . features ;
910+ const featureMap = features . reduce (
956911 ( acc , f ) => {
957912 acc [ f . key ] = f ;
958913 return acc ;
@@ -962,7 +917,7 @@ export class BucketClient {
962917
963918 const { enableTracking = true , meta : _ , ...context } = options ;
964919
965- const evaluated = featureDefinitions . map ( ( feature ) =>
920+ const evaluated = features . map ( ( feature ) =>
966921 evaluateFeatureRules ( {
967922 featureKey : feature . key ,
968923 rules : feature . targeting . rules . map ( ( r ) => ( { ...r , value : true } ) ) ,
0 commit comments