Skip to content

Commit 5b56bba

Browse files
committed
chore: adding fdv2 configs
1 parent 206d682 commit 5b56bba

9 files changed

Lines changed: 241 additions & 225 deletions

File tree

packages/sdk/browser/contract-tests/entity/src/ClientEntity.ts

Lines changed: 8 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,22 @@
1-
import {
2-
createClient,
3-
InitializerEntry,
4-
LDOptions,
5-
ModeDefinition,
6-
SynchronizerEntry,
7-
} from '@launchdarkly/js-client-sdk';
1+
import { createClient, LDContext, LDOptions } from '@launchdarkly/js-client-sdk';
82
import {
93
ClientEntity,
104
CreateInstanceParams,
115
IClientEntity,
12-
makeDefaultInitialContext,
13-
makeSdkConfig,
14-
SDKConfigDataInitializer,
15-
SDKConfigDataSynchronizer,
16-
SDKConfigModeDefinition,
17-
SDKConfigParams,
6+
parseClientOptions,
187
} from '@launchdarkly/js-contract-test-utils/client';
198

20-
function translateInitializer(init: SDKConfigDataInitializer): InitializerEntry | undefined {
21-
if (init.polling) {
22-
return {
23-
type: 'polling',
24-
...(init.polling.pollIntervalMs !== undefined && {
25-
pollInterval: init.polling.pollIntervalMs / 1000,
26-
}),
27-
...(init.polling.baseUri && {
28-
endpoints: { pollingBaseUri: init.polling.baseUri },
29-
}),
30-
};
31-
}
32-
return undefined;
33-
}
34-
35-
function translateSynchronizer(sync: SDKConfigDataSynchronizer): SynchronizerEntry | undefined {
36-
if (sync.streaming) {
37-
return {
38-
type: 'streaming',
39-
...(sync.streaming.initialRetryDelayMs !== undefined && {
40-
initialReconnectDelay: sync.streaming.initialRetryDelayMs / 1000,
41-
}),
42-
...(sync.streaming.baseUri && {
43-
endpoints: { streamingBaseUri: sync.streaming.baseUri },
44-
}),
45-
};
46-
}
47-
if (sync.polling) {
48-
return {
49-
type: 'polling',
50-
...(sync.polling.pollIntervalMs !== undefined && {
51-
pollInterval: sync.polling.pollIntervalMs / 1000,
52-
}),
53-
...(sync.polling.baseUri && {
54-
endpoints: { pollingBaseUri: sync.polling.baseUri },
55-
}),
56-
};
57-
}
58-
return undefined;
59-
}
60-
61-
function translateModeDefinition(modeDef: SDKConfigModeDefinition): ModeDefinition {
62-
const initializers: InitializerEntry[] = (modeDef.initializers ?? [])
63-
.map(translateInitializer)
64-
.filter((x): x is InitializerEntry => x !== undefined);
65-
66-
const synchronizers: SynchronizerEntry[] = (modeDef.synchronizers ?? [])
67-
.map(translateSynchronizer)
68-
.filter((x): x is SynchronizerEntry => x !== undefined);
69-
70-
return { initializers, synchronizers };
71-
}
72-
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 {
78-
const isSet = (x?: unknown) => x !== null && x !== undefined;
79-
const maybeTime = (seconds?: number) => (isSet(seconds) ? seconds! / 1000 : undefined);
80-
81-
const cf = { ...makeSdkConfig(options, tag), fetchGoals: false } as LDOptions;
82-
83-
if (options.dataSystem?.payloadFilter) {
84-
cf.payloadFilterKey = options.dataSystem.payloadFilter;
85-
}
86-
87-
if (options.dataSystem) {
88-
const dataSystem: any = {};
89-
90-
if (options.dataSystem.connectionModeConfig) {
91-
const connMode = options.dataSystem.connectionModeConfig;
92-
dataSystem.automaticModeSwitching = connMode.initialConnectionMode
93-
? { type: 'manual', initialConnectionMode: connMode.initialConnectionMode }
94-
: false;
95-
96-
if (connMode.customConnectionModes) {
97-
const connectionModes: Record<string, any> = {};
98-
Object.entries(connMode.customConnectionModes).forEach(([modeName, modeDef]) => {
99-
connectionModes[modeName] = translateModeDefinition(modeDef);
100-
101-
// Per-entry endpoint overrides also set global URIs for ServiceEndpoints
102-
// compatibility. These override the serviceEndpoints values above.
103-
(modeDef.synchronizers ?? []).forEach((sync) => {
104-
if (sync.streaming?.baseUri) {
105-
cf.streamUri = sync.streaming.baseUri;
106-
cf.streamInitialReconnectDelay = maybeTime(sync.streaming.initialRetryDelayMs);
107-
}
108-
if (sync.polling?.baseUri) {
109-
cf.baseUri = sync.polling.baseUri;
110-
}
111-
});
112-
(modeDef.initializers ?? []).forEach((init) => {
113-
if (init.polling?.baseUri) {
114-
cf.baseUri = init.polling.baseUri;
115-
}
116-
});
117-
});
118-
dataSystem.connectionModes = connectionModes;
119-
}
120-
}
121-
122-
(cf as any).dataSystem = dataSystem;
123-
}
124-
125-
return cf;
126-
}
127-
1289
export async function newSdkClientEntity(
12910
_id: string,
13011
options: CreateInstanceParams,
13112
): Promise<IClientEntity> {
132-
const timeout =
133-
options.configuration.startWaitTimeMs !== null &&
134-
options.configuration.startWaitTimeMs !== undefined
135-
? options.configuration.startWaitTimeMs
136-
: 5000;
137-
138-
const sdkConfig = makeBrowserSdkConfig(options.configuration, options.tag);
139-
const initialContext =
140-
options.configuration.clientSide?.initialUser ||
141-
options.configuration.clientSide?.initialContext ||
142-
makeDefaultInitialContext();
13+
const { timeout, sdkConfig, initialContext, credential, initCanFail } =
14+
parseClientOptions(options);
14315

14416
const client = createClient(
145-
options.configuration.credential || 'unknown-env-id',
146-
initialContext,
147-
sdkConfig,
17+
credential,
18+
initialContext as LDContext,
19+
{ ...sdkConfig, fetchGoals: false } as LDOptions,
14820
);
14921

15022
let failed = false;
@@ -158,7 +30,7 @@ export async function newSdkClientEntity(
15830
} catch (_) {
15931
failed = true;
16032
}
161-
if (failed && !options.configuration.initCanFail) {
33+
if (failed && !initCanFail) {
16234
client.close();
16335
throw new Error('client initialization failed');
16436
}

packages/sdk/browser/contract-tests/entity/src/TestHarnessWebSocket.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
import {
2-
CLIENT_SIDE_CAPABILITIES,
2+
Capability,
33
IClientEntity,
44
TestHarnessWebSocketBuilder,
55
} from '@launchdarkly/js-contract-test-utils/client';
66

77
import { newSdkClientEntity } from './ClientEntity';
88

9+
const CAPABILITIES: Capability[] = [
10+
'client-side',
11+
'service-endpoints',
12+
'tags',
13+
'user-type',
14+
'inline-context-all',
15+
'anonymous-redaction',
16+
'strongly-typed',
17+
'client-prereq-events',
18+
'client-per-context-summaries',
19+
'track-hooks',
20+
];
21+
922
export function createTestHarnessWebSocket() {
1023
const entities = new Map<string, IClientEntity>();
1124

1225
return new TestHarnessWebSocketBuilder()
13-
.setCapabilities(CLIENT_SIDE_CAPABILITIES)
26+
.setCapabilities(CAPABILITIES)
1427
.onCreateClient(async (id, params) => {
1528
const entity = await newSdkClientEntity(id, params);
1629
entities.set(id, entity);

packages/sdk/react-native/contract-tests/entity/App.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,25 @@ import { StyleSheet, Text, View } from 'react-native';
33

44
import {
55
Capability,
6-
CLIENT_SIDE_CAPABILITIES,
76
IClientEntity,
87
TestHarnessWebSocketBuilder,
98
} from '@launchdarkly/js-contract-test-utils/client';
109

1110
import { newSdkClientEntity } from './src/ClientEntity';
1211

13-
const RN_CAPABILITIES: Capability[] = [...CLIENT_SIDE_CAPABILITIES, 'mobile'];
12+
const RN_CAPABILITIES: Capability[] = [
13+
'client-side',
14+
'mobile',
15+
'service-endpoints',
16+
'tags',
17+
'user-type',
18+
'inline-context-all',
19+
'anonymous-redaction',
20+
'strongly-typed',
21+
'client-prereq-events',
22+
'client-per-context-summaries',
23+
'track-hooks',
24+
];
1425

1526
const styles = StyleSheet.create({
1627
container: {

packages/sdk/react-native/contract-tests/entity/src/ClientEntity.ts

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import {
22
ClientEntity,
33
CreateInstanceParams,
44
IClientEntity,
5-
makeDefaultInitialContext,
6-
makeSdkConfig,
5+
parseClientOptions,
76
} from '@launchdarkly/js-contract-test-utils/client';
87
import {
98
AutoEnvAttributes,
9+
LDContext,
1010
LDOptions,
1111
ReactNativeLDClient,
1212
} from '@launchdarkly/react-native-client-sdk';
@@ -15,57 +15,50 @@ export async function newSdkClientEntity(
1515
_id: string,
1616
options: CreateInstanceParams,
1717
): Promise<IClientEntity> {
18-
const timeout =
19-
options.configuration.startWaitTimeMs !== null &&
20-
options.configuration.startWaitTimeMs !== undefined
21-
? options.configuration.startWaitTimeMs
22-
: 5000;
18+
const { timeout, sdkConfig, initialContext, initCanFail } = parseClientOptions(options);
2319

24-
// Build base config, then add RN-specific options
25-
const baseConfig = makeSdkConfig(options.configuration, options.tag);
26-
const sdkConfig: LDOptions = {
27-
...baseConfig,
20+
// Add RN-specific options
21+
const rnConfig: LDOptions = {
22+
...sdkConfig,
2823
automaticNetworkHandling: false,
2924
automaticBackgroundHandling: false,
3025
} as LDOptions;
3126

3227
// RN uses initialConnectionMode instead of streaming boolean
3328
if (options.configuration.polling) {
34-
sdkConfig.initialConnectionMode = 'polling';
29+
rnConfig.initialConnectionMode = 'polling';
3530
}
3631
if (options.configuration.streaming) {
37-
sdkConfig.initialConnectionMode = 'streaming';
32+
rnConfig.initialConnectionMode = 'streaming';
3833
}
3934
// Remove the browser-style streaming field — RN doesn't use it
40-
delete (sdkConfig as Record<string, unknown>).streaming;
35+
delete (rnConfig as Record<string, unknown>).streaming;
4136

4237
const autoEnvAttributes = options.configuration.clientSide?.includeEnvironmentAttributes
4338
? AutoEnvAttributes.Enabled
4439
: AutoEnvAttributes.Disabled;
4540

46-
const initialContext =
47-
options.configuration.clientSide?.initialUser ||
48-
options.configuration.clientSide?.initialContext ||
49-
makeDefaultInitialContext();
50-
5141
const client = new ReactNativeLDClient(
5242
options.configuration.credential || 'unknown-mobile-key',
5343
autoEnvAttributes,
54-
sdkConfig,
44+
rnConfig,
5545
);
5646

5747
let failed = false;
5848
try {
5949
await Promise.race([
60-
client.identify(initialContext, { timeout: timeout / 1000, waitForNetworkResults: true }),
50+
client.identify(initialContext as LDContext, {
51+
timeout: timeout / 1000,
52+
waitForNetworkResults: true,
53+
}),
6154
new Promise((_resolve, reject) => {
6255
setTimeout(reject, timeout);
6356
}),
6457
]);
6558
} catch (_) {
6659
failed = true;
6760
}
68-
if (failed && !options.configuration.initCanFail) {
61+
if (failed && !initCanFail) {
6962
client.close();
7063
throw new Error('client initialization failed');
7164
}

packages/sdk/react/contract-tests/app/ClientEntity.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,11 @@
33
import { useEffect } from 'react';
44

55
import {
6-
makeSdkConfig as baseMakeSdkConfig,
76
CommandParams,
87
doCommand,
98
IClientEntity,
10-
SDKConfigParams,
119
} from '@launchdarkly/js-contract-test-utils/client';
12-
import { LDOptions, LDReactClient, useLDClient } from '@launchdarkly/react-sdk';
13-
14-
export function makeSdkConfig(options: SDKConfigParams, tag: string): LDOptions {
15-
return { ...baseMakeSdkConfig(options, tag), fetchGoals: false } as LDOptions;
16-
}
10+
import { LDReactClient, useLDClient } from '@launchdarkly/react-sdk';
1711

1812
export type CommandHandler = (params: CommandParams) => Promise<unknown>;
1913

0 commit comments

Comments
 (0)