@@ -11,7 +11,6 @@ import {
1111 StandardResolutionReasons ,
1212 Logger ,
1313 ProviderEvents ,
14- OpenFeature ,
1514 OpenFeatureEventEmitter ,
1615} from "@openfeature/web-sdk" ;
1716import type SplitIO from "@splitsoftware/splitio/types/splitio" ;
@@ -22,6 +21,7 @@ type Consumer = {
2221} ;
2322
2423const CONTROL_VALUE_ERROR_MESSAGE = "Received the 'control' value from Split." ;
24+ const CONTROL_TREATMENT = 'control' ;
2525
2626export class OpenFeatureSplitProvider implements Provider {
2727 metadata = {
@@ -41,130 +41,117 @@ export class OpenFeatureSplitProvider implements Provider {
4141 this . events . emit ( ProviderEvents . Ready )
4242 } ;
4343
44- // If client is ready, resolve immediately
45- if ( this . isClientReady ( ) ) {
44+ const onSdkTimedOut = ( ) => {
45+ console . log ( `${ this . metadata . name } provider couldn't initialize` ) ;
46+ this . events . emit ( ProviderEvents . Error ) ;
47+ } ;
48+
49+ const clientStatus = ( this . client as any ) . __getStatus ( ) ;
50+ if ( clientStatus . isReady ) {
4651 onSdkReady ( ) ;
47- } else {
48- this . client . on ( this . client . Event . SDK_READY , onSdkReady ) ;
52+ return ;
53+ }
54+ if ( clientStatus . hasTimedout || clientStatus . isTimedOut ) {
55+ onSdkTimedOut ( ) ;
56+ return ;
4957 }
50- }
51-
52- // Safe method to check if client is ready
53- private isClientReady ( ) : boolean {
54- return ( this . client as any ) . __getStatus ( ) . isReady ;
58+ this . client . on ( this . client . Event . SDK_READY , onSdkReady ) ;
59+ this . client . on ( this . client . Event . SDK_READY_TIMED_OUT , onSdkTimedOut ) ;
5560 }
5661
5762 resolveBooleanEvaluation (
5863 flagKey : string ,
59- defaultValue : boolean ,
64+ _ : boolean ,
6065 context : EvaluationContext ,
6166 _logger : Logger
6267 ) : ResolutionDetails < boolean > {
6368 const details = this . evaluateTreatment (
6469 flagKey ,
6570 this . transformContext ( context ) ,
66- defaultValue . toString ( )
6771 ) ;
6872
69- let value : boolean ;
70- switch ( details . value as unknown ) {
71- case "on" :
72- case "true" :
73- case true :
74- value = true ;
75- break ;
76- case "off" :
77- case "false" :
78- case false :
79- value = false ;
80- break ;
81- case "control" :
82- throw new FlagNotFoundError ( CONTROL_VALUE_ERROR_MESSAGE ) ;
83- default :
84- throw new ParseError ( `Invalid boolean value for ${ details . value } ` ) ;
73+ const treatment = details . value . toLowerCase ( ) ;
74+
75+ if ( treatment === 'on' || treatment === 'true' ) {
76+ return { ...details , value : true } ;
8577 }
86- return { ...details , value } ;
78+
79+ if ( treatment === 'off' || treatment === 'false' ) {
80+ return { ...details , value : false } ;
81+ }
82+
83+ throw new ParseError ( `Invalid boolean value for ${ treatment } ` ) ;
8784 }
8885
8986 resolveStringEvaluation (
9087 flagKey : string ,
91- defaultValue : string ,
88+ _ : string ,
9289 context : EvaluationContext ,
9390 _logger : Logger
9491 ) : ResolutionDetails < string > {
9592 const details = this . evaluateTreatment (
9693 flagKey ,
9794 this . transformContext ( context ) ,
98- defaultValue
9995 ) ;
100- if ( details . value === "control" ) {
101- throw new FlagNotFoundError ( CONTROL_VALUE_ERROR_MESSAGE ) ;
102- }
10396 return details ;
10497 }
10598
10699 resolveNumberEvaluation (
107100 flagKey : string ,
108- defaultValue : number ,
101+ _ : number ,
109102 context : EvaluationContext ,
110103 _logger : Logger
111104 ) : ResolutionDetails < number > {
112105 const details = this . evaluateTreatment (
113106 flagKey ,
114107 this . transformContext ( context ) ,
115- defaultValue . toString ( )
116108 ) ;
117109 return { ...details , value : this . parseValidNumber ( details . value ) } ;
118110 }
119111
120112 resolveObjectEvaluation < U extends JsonValue > (
121113 flagKey : string ,
122- defaultValue : U ,
114+ _ : U ,
123115 context : EvaluationContext ,
124116 _logger : Logger
125117 ) : ResolutionDetails < U > {
126118 const details = this . evaluateTreatment (
127119 flagKey ,
128- this . transformContext ( context ) ,
129- JSON . stringify ( defaultValue )
120+ this . transformContext ( context )
130121 ) ;
131122 return { ...details , value : this . parseValidJsonObject ( details . value ) } ;
132123 }
133124
134125 private evaluateTreatment (
135126 flagKey : string ,
136- consumer : Consumer ,
137- defaultValue : string
127+ consumer : Consumer
138128 ) : ResolutionDetails < string > {
139129 if ( ! consumer . key ) {
140130 throw new TargetingKeyMissingError (
141- " The Split provider requires a targeting key."
131+ ' The Split provider requires a targeting key.'
142132 ) ;
143- } else {
144- // The SDK should be ready by now, but if not, return default value
145- // Use our isClientReady helper to safely check
146- if ( ! this . isClientReady ( ) ) {
147- return {
148- value : defaultValue ,
149- variant : defaultValue ,
150- reason : StandardResolutionReasons . DEFAULT
151- } ;
152- }
153- const value = this . client . getTreatment (
154- flagKey ,
155- consumer . attributes
133+ }
134+ if ( flagKey == null || flagKey === '' ) {
135+ throw new FlagNotFoundError (
136+ 'flagKey must be a non-empty string'
156137 ) ;
157- // Create resolution details and add flagKey as additional property for tests
158- const details : ResolutionDetails < string > = {
159- value : value ,
160- variant : value ,
161- reason : StandardResolutionReasons . TARGETING_MATCH ,
162- } ;
163-
164- // Add flagKey for OpenFeature v1 compatibility, using assertion to avoid TypeScript errors
165- ( details as any ) . flagKey = flagKey ;
166- return details ;
167138 }
139+ const { treatment : value , config } : SplitIO . TreatmentWithConfig = this . client . getTreatmentWithConfig (
140+ flagKey ,
141+ consumer . attributes
142+ ) ;
143+
144+ if ( value === CONTROL_TREATMENT ) {
145+ throw new FlagNotFoundError ( CONTROL_VALUE_ERROR_MESSAGE ) ;
146+ }
147+ const flagMetadata = { config : config ? config : '' } ;
148+ const details : ResolutionDetails < string > = {
149+ value : value ,
150+ variant : value ,
151+ flagMetadata : flagMetadata ,
152+ reason : StandardResolutionReasons . TARGETING_MATCH ,
153+ } ;
154+ return details ;
168155 }
169156
170157 //Transform the context into an object useful for the Split API, an key string with arbitrary Split "Attributes".
0 commit comments