11import {
22 createClient ,
33 InitializerEntry ,
4- LDClient ,
5- LDLogger ,
64 LDOptions ,
75 ModeDefinition ,
86 SynchronizerEntry ,
97} from '@launchdarkly/js-client-sdk' ;
108import {
11- CommandParams ,
12- CommandType ,
9+ ClientEntity ,
1310 CreateInstanceParams ,
14- makeLogger ,
11+ IClientEntity ,
12+ makeDefaultInitialContext ,
13+ makeSdkConfig ,
1514 SDKConfigDataInitializer ,
1615 SDKConfigDataSynchronizer ,
1716 SDKConfigModeDefinition ,
1817 SDKConfigParams ,
19- ClientSideTestHook as TestHook ,
20- ValueType ,
2118} from '@launchdarkly/js-contract-test-utils/client' ;
2219
23- export const badCommandError = new Error ( 'unsupported command' ) ;
24- export const malformedCommand = new Error ( 'command was malformed' ) ;
25-
2620function translateInitializer ( init : SDKConfigDataInitializer ) : InitializerEntry | undefined {
2721 if ( init . polling ) {
2822 return {
@@ -76,25 +70,15 @@ function translateModeDefinition(modeDef: SDKConfigModeDefinition): ModeDefiniti
7670 return { initializers, synchronizers } ;
7771}
7872
79- function makeSdkConfig ( options : SDKConfigParams , tag : string ) {
80- if ( ! options . clientSide ) {
81- throw new Error ( 'configuration did not include clientSide options' ) ;
82- }
83-
73+ /**
74+ * Browser-specific makeSdkConfig that wraps the shared base config with
75+ * FDv2 data system translation and browser-specific options.
76+ */
77+ function makeBrowserSdkConfig ( options : SDKConfigParams , tag : string ) : LDOptions {
8478 const isSet = ( x ?: unknown ) => x !== null && x !== undefined ;
85- const maybeTime = ( seconds ?: number ) => ( isSet ( seconds ) ? seconds / 1000 : undefined ) ;
79+ const maybeTime = ( seconds ?: number ) => ( isSet ( seconds ) ? seconds ! / 1000 : undefined ) ;
8680
87- const cf : LDOptions = {
88- withReasons : options . clientSide . evaluationReasons ,
89- logger : makeLogger ( `${ tag } .sdk` ) ,
90- useReport : options . clientSide . useReport ?? undefined ,
91- } ;
92-
93- if ( options . serviceEndpoints ) {
94- cf . streamUri = options . serviceEndpoints . streaming ;
95- cf . baseUri = options . serviceEndpoints . polling ;
96- cf . eventsUri = options . serviceEndpoints . events ;
97- }
81+ const cf = { ...makeSdkConfig ( options , tag ) , fetchGoals : false } as LDOptions ;
9882
9983 if ( options . dataSystem ?. payloadFilter ) {
10084 cf . payloadFilterKey = options . dataSystem . payloadFilter ;
@@ -136,189 +120,33 @@ function makeSdkConfig(options: SDKConfigParams, tag: string) {
136120 }
137121
138122 ( cf as any ) . dataSystem = dataSystem ;
139- } else {
140- if ( options . polling ) {
141- if ( options . polling . baseUri ) {
142- cf . baseUri = options . polling . baseUri ;
143- }
144- }
145-
146- if ( options . streaming ) {
147- if ( options . streaming . baseUri ) {
148- cf . streamUri = options . streaming . baseUri ;
149- }
150- cf . streaming = true ;
151- cf . streamInitialReconnectDelay = maybeTime ( options . streaming . initialRetryDelayMs ) ;
152- }
153123 }
154124
155- if ( options . events ) {
156- if ( options . events . baseUri ) {
157- cf . eventsUri = options . events . baseUri ;
158- }
159- cf . allAttributesPrivate = options . events . allAttributesPrivate ;
160- cf . capacity = options . events . capacity ;
161- cf . diagnosticOptOut = ! options . events . enableDiagnostics ;
162- cf . flushInterval = maybeTime ( options . events . flushIntervalMs ) ;
163- cf . privateAttributes = options . events . globalPrivateAttributes ;
164- } else {
165- cf . sendEvents = false ;
166- }
167-
168- if ( options . tags ) {
169- cf . applicationInfo = {
170- id : options . tags . applicationId ,
171- version : options . tags . applicationVersion ,
172- } ;
173- }
174-
175- if ( options . hooks ) {
176- cf . hooks = options . hooks . hooks . map (
177- ( hook ) => new TestHook ( hook . name , hook . callbackUri , hook . data , hook . errors ) ,
178- ) ;
179- }
180-
181- cf . fetchGoals = false ;
182-
183125 return cf ;
184126}
185127
186- function makeDefaultInitialContext ( ) {
187- return { kind : 'user' , key : 'key-not-specified' } ;
188- }
189-
190- export class ClientEntity {
191- constructor (
192- private readonly _client : LDClient ,
193- private readonly _logger : LDLogger ,
194- ) { }
195-
196- close ( ) {
197- this . _client . close ( ) ;
198- this . _logger . info ( 'Test ended' ) ;
199- }
200-
201- async doCommand ( params : CommandParams ) {
202- this . _logger . info ( `Received command: ${ params . command } ` ) ;
203- switch ( params . command ) {
204- case CommandType . EvaluateFlag : {
205- const evaluationParams = params . evaluate ;
206- if ( ! evaluationParams ) {
207- throw malformedCommand ;
208- }
209- if ( evaluationParams . detail ) {
210- switch ( evaluationParams . valueType ) {
211- case ValueType . Bool :
212- return this . _client . boolVariationDetail (
213- evaluationParams . flagKey ,
214- evaluationParams . defaultValue as boolean ,
215- ) ;
216- case ValueType . Int : // Intentional fallthrough.
217- case ValueType . Double :
218- return this . _client . numberVariationDetail (
219- evaluationParams . flagKey ,
220- evaluationParams . defaultValue as number ,
221- ) ;
222- case ValueType . String :
223- return this . _client . stringVariationDetail (
224- evaluationParams . flagKey ,
225- evaluationParams . defaultValue as string ,
226- ) ;
227- default :
228- return this . _client . variationDetail (
229- evaluationParams . flagKey ,
230- evaluationParams . defaultValue ,
231- ) ;
232- }
233- }
234- switch ( evaluationParams . valueType ) {
235- case ValueType . Bool :
236- return {
237- value : this . _client . boolVariation (
238- evaluationParams . flagKey ,
239- evaluationParams . defaultValue as boolean ,
240- ) ,
241- } ;
242- case ValueType . Int : // Intentional fallthrough.
243- case ValueType . Double :
244- return {
245- value : this . _client . numberVariation (
246- evaluationParams . flagKey ,
247- evaluationParams . defaultValue as number ,
248- ) ,
249- } ;
250- case ValueType . String :
251- return {
252- value : this . _client . stringVariation (
253- evaluationParams . flagKey ,
254- evaluationParams . defaultValue as string ,
255- ) ,
256- } ;
257- default :
258- return {
259- value : this . _client . variation (
260- evaluationParams . flagKey ,
261- evaluationParams . defaultValue ,
262- ) ,
263- } ;
264- }
265- }
266-
267- case CommandType . EvaluateAllFlags :
268- return { state : this . _client . allFlags ( ) } ;
269-
270- case CommandType . IdentifyEvent : {
271- const identifyParams = params . identifyEvent ;
272- if ( ! identifyParams ) {
273- throw malformedCommand ;
274- }
275- await this . _client . identify ( identifyParams . user || identifyParams . context ) ;
276- return undefined ;
277- }
278-
279- case CommandType . CustomEvent : {
280- const customEventParams = params . customEvent ;
281- if ( ! customEventParams ) {
282- throw malformedCommand ;
283- }
284- this . _client . track (
285- customEventParams . eventKey ,
286- customEventParams . data ,
287- customEventParams . metricValue ,
288- ) ;
289- return undefined ;
290- }
291-
292- case CommandType . FlushEvents :
293- this . _client . flush ( ) ;
294- return undefined ;
295-
296- default :
297- throw badCommandError ;
298- }
299- }
300- }
301-
302- export async function newSdkClientEntity ( options : CreateInstanceParams ) {
303- const logger = makeLogger ( options . tag ) ;
304-
305- logger . info ( `Creating client with configuration: ${ JSON . stringify ( options . configuration ) } ` ) ;
306-
128+ export async function newSdkClientEntity (
129+ _id : string ,
130+ options : CreateInstanceParams ,
131+ ) : Promise < IClientEntity > {
307132 const timeout =
308133 options . configuration . startWaitTimeMs !== null &&
309134 options . configuration . startWaitTimeMs !== undefined
310135 ? options . configuration . startWaitTimeMs
311136 : 5000 ;
312- const sdkConfig = makeSdkConfig ( options . configuration , options . tag ) ;
137+
138+ const sdkConfig = makeBrowserSdkConfig ( options . configuration , options . tag ) ;
313139 const initialContext =
314140 options . configuration . clientSide ?. initialUser ||
315141 options . configuration . clientSide ?. initialContext ||
316142 makeDefaultInitialContext ( ) ;
143+
317144 const client = createClient (
318145 options . configuration . credential || 'unknown-env-id' ,
319146 initialContext ,
320147 sdkConfig ,
321148 ) ;
149+
322150 let failed = false ;
323151 try {
324152 await Promise . race ( [
@@ -328,13 +156,12 @@ export async function newSdkClientEntity(options: CreateInstanceParams) {
328156 } ) ,
329157 ] ) ;
330158 } catch ( _ ) {
331- // we get here if waitForInitialization() rejects or if we timed out
332159 failed = true ;
333160 }
334161 if ( failed && ! options . configuration . initCanFail ) {
335162 client . close ( ) ;
336163 throw new Error ( 'client initialization failed' ) ;
337164 }
338165
339- return new ClientEntity ( client , logger ) ;
166+ return new ClientEntity ( client , options . tag ) ;
340167}
0 commit comments