From adfeb971fe690b5f4169a7ad5e1ac0b90a62eb31 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 12:01:56 -0500 Subject: [PATCH 01/10] chore: replaced legacy js sdk with modern Browser SDK --- packages/sdk/react-universal/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk/react-universal/package.json b/packages/sdk/react-universal/package.json index 39e341e7c5..f15db03456 100644 --- a/packages/sdk/react-universal/package.json +++ b/packages/sdk/react-universal/package.json @@ -67,9 +67,9 @@ "typescript": "5.1.6" }, "dependencies": { + "@launchdarkly/js-client-sdk": "^0.4.1", "@launchdarkly/js-client-sdk-common": "^1.1.4", - "@launchdarkly/node-server-sdk": "^9.4.6", - "launchdarkly-js-client-sdk": "^3.4.0" + "@launchdarkly/node-server-sdk": "^9.4.6" }, "peerDependencies": { "react": "*" From 24024387ae18d90d392da93f31a49df5944289ae Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 12:30:11 -0500 Subject: [PATCH 02/10] chore: update LD provider --- packages/sdk/react-universal/src/client/LDProvider.tsx | 10 +++++++--- packages/sdk/react-universal/src/types.ts | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/sdk/react-universal/src/client/LDProvider.tsx b/packages/sdk/react-universal/src/client/LDProvider.tsx index af8a319390..230d9012bd 100644 --- a/packages/sdk/react-universal/src/client/LDProvider.tsx +++ b/packages/sdk/react-universal/src/client/LDProvider.tsx @@ -1,9 +1,9 @@ 'use client'; -import { initialize, type LDOptions } from 'launchdarkly-js-client-sdk'; import { type PropsWithChildren, useEffect, useState } from 'react'; import React from 'react'; +import { initialize, type LDOptions } from '@launchdarkly/js-client-sdk'; import type { LDContext, LDFlagSet } from '@launchdarkly/node-server-sdk'; import { isServer } from '../isServer'; @@ -14,6 +14,7 @@ import { setupListeners } from './setupListeners'; type LDProps = { clientSideID: string; context: LDContext; + bootstrap: LDFlagSet; options?: LDOptions; }; @@ -23,28 +24,31 @@ type LDProps = { * * @param clientSideID Your LaunchDarkly client side id. * @param context The LDContext for evaluation. + * @param bootstrap LDFlagSet used to bootstrap * @param options Configuration options for the js sdk. See {@link LDOptions}. * @param children Your react application to be rendered. */ export const LDProvider = ({ clientSideID, context, + bootstrap, options, children, }: PropsWithChildren) => { let jsSdk: JSSdk = undefined as any; if (!isServer) { - jsSdk = initialize(clientSideID ?? '', context, options); + jsSdk = initialize(clientSideID ?? '', options); } const [state, setState] = useState({ jsSdk, context, - bootstrap: options?.bootstrap as LDFlagSet, + bootstrap, }); useEffect(() => { setupListeners(setState, jsSdk); + jsSdk.identify(context, { bootstrap }); }, []); return {children}; diff --git a/packages/sdk/react-universal/src/types.ts b/packages/sdk/react-universal/src/types.ts index 78ce8e871b..e82f06460c 100644 --- a/packages/sdk/react-universal/src/types.ts +++ b/packages/sdk/react-universal/src/types.ts @@ -1,6 +1,6 @@ import type { LDClient as NodeSdk } from '@launchdarkly/node-server-sdk'; -export type { LDClient as JSSdk } from 'launchdarkly-js-client-sdk'; +export type { LDClient as JSSdk } from '@launchdarkly/js-client-sdk'; export type { NodeSdk }; From 39ad5d14d22844cc958f4727576fef54f1e3ec74 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 12:40:54 -0500 Subject: [PATCH 03/10] feat: add more hooks to sdk --- .../react-universal/example/app/layout.tsx | 3 +- .../hooks/variation/useTypedVariation.ts | 54 +++++++------- .../client/hooks/variation/useVariation.ts | 24 +++++++ .../sdk/react-universal/src/ldClientRsc.ts | 71 ++++++++++++++++++- .../server/hooks/variation/useVariationRsc.ts | 44 ++++++++++++ 5 files changed, 166 insertions(+), 30 deletions(-) diff --git a/packages/sdk/react-universal/example/app/layout.tsx b/packages/sdk/react-universal/example/app/layout.tsx index 7b765b7d97..0ae5a2e996 100644 --- a/packages/sdk/react-universal/example/app/layout.tsx +++ b/packages/sdk/react-universal/example/app/layout.tsx @@ -35,7 +35,8 @@ export default async function RootLayout({ {children} diff --git a/packages/sdk/react-universal/src/client/hooks/variation/useTypedVariation.ts b/packages/sdk/react-universal/src/client/hooks/variation/useTypedVariation.ts index 34beff06cd..f22283a6b0 100644 --- a/packages/sdk/react-universal/src/client/hooks/variation/useTypedVariation.ts +++ b/packages/sdk/react-universal/src/client/hooks/variation/useTypedVariation.ts @@ -9,15 +9,15 @@ export const useTypedVariation = const ldClient = useLDClient(); switch (typeof defaultValue) { - // case 'boolean': - // return ldClient.boolVariation(key, defaultValue as boolean) as T; - // case 'number': - // return ldClient.numberVariation(key, defaultValue as number) as T; - // case 'string': - // return ldClient.stringVariation(key, defaultValue as string) as T; - // case 'undefined': - // case 'object': - // return ldClient.jsonVariation(key, defaultValue) as T; + case 'boolean': + return ldClient.boolVariation(key, defaultValue as boolean) as T; + case 'number': + return ldClient.numberVariation(key, defaultValue as number) as T; + case 'string': + return ldClient.stringVariation(key, defaultValue as string) as T; + case 'undefined': + case 'object': + return ldClient.jsonVariation(key, defaultValue) as T; default: return ldClient.variation(key, defaultValue); } @@ -30,24 +30,24 @@ export const useTypedVariationDetail = ; - // case 'number': - // return ldClient.numberVariationDetail( - // key, - // defaultValue as number, - // ) as LDEvaluationDetailTyped; - // case 'string': - // return ldClient.stringVariationDetail( - // key, - // defaultValue as string, - // ) as LDEvaluationDetailTyped; - // case 'undefined': - // case 'object': - // return ldClient.jsonVariationDetail(key, defaultValue) as LDEvaluationDetailTyped; + case 'boolean': + return ldClient.boolVariationDetail( + key, + defaultValue as boolean, + ) as LDEvaluationDetailTyped; + case 'number': + return ldClient.numberVariationDetail( + key, + defaultValue as number, + ) as LDEvaluationDetailTyped; + case 'string': + return ldClient.stringVariationDetail( + key, + defaultValue as string, + ) as LDEvaluationDetailTyped; + case 'undefined': + case 'object': + return ldClient.jsonVariationDetail(key, defaultValue) as LDEvaluationDetailTyped; default: return ldClient.variationDetail(key, defaultValue) as LDEvaluationDetailTyped; } diff --git a/packages/sdk/react-universal/src/client/hooks/variation/useVariation.ts b/packages/sdk/react-universal/src/client/hooks/variation/useVariation.ts index c8d06c1f70..94e46b9db8 100644 --- a/packages/sdk/react-universal/src/client/hooks/variation/useVariation.ts +++ b/packages/sdk/react-universal/src/client/hooks/variation/useVariation.ts @@ -1,5 +1,17 @@ import { useTypedVariation, useTypedVariationDetail } from './useTypedVariation'; +export const useBoolVariation = (key: string, defaultValue: boolean) => + useTypedVariation(key, defaultValue); + +export const useStringVariation = (key: string, defaultValue: string) => + useTypedVariation(key, defaultValue); + +export const useNumberVariation = (key: string, defaultValue: number) => + useTypedVariation(key, defaultValue); + +export const useJsonVariation = (key: string, defaultValue?: undefined) => + useTypedVariation(key, defaultValue); + export const useVariation = (key: string, defaultValue?: boolean) => useTypedVariation(key, defaultValue); @@ -10,5 +22,17 @@ export const useVariation = (key: string, defaultValue?: boolean) => * @param key * @param defaultValue */ +export const useBoolVariationDetail = (key: string, defaultValue: boolean) => + useTypedVariationDetail(key, defaultValue); + +export const useStringVariationDetail = (key: string, defaultValue: string) => + useTypedVariationDetail(key, defaultValue); + +export const useNumberVariationDetail = (key: string, defaultValue: number) => + useTypedVariationDetail(key, defaultValue); + +export const useJsonVariationDetail = (key: string, defaultValue?: undefined) => + useTypedVariationDetail(key, defaultValue); + export const useVariationDetail = (key: string, defaultValue?: boolean) => useTypedVariationDetail(key, defaultValue); diff --git a/packages/sdk/react-universal/src/ldClientRsc.ts b/packages/sdk/react-universal/src/ldClientRsc.ts index 7fd333839b..df4427a468 100644 --- a/packages/sdk/react-universal/src/ldClientRsc.ts +++ b/packages/sdk/react-universal/src/ldClientRsc.ts @@ -1,3 +1,4 @@ +import { LDEvaluationDetailTyped } from '@launchdarkly/js-client-sdk'; import type { LDContext, LDEvaluationDetail, @@ -29,17 +30,83 @@ export class LDClientRsc implements PartialJSSdk { return this._ldContext; } + /** + * + * Call the server sdk variation for analytics purposes. + */ + boolVariation(key: string, defaultValue: boolean): boolean { + if (isServer) { + global.nodeSdk.boolVariation(key, this._ldContext, defaultValue).then(/* ignore */); + } + return this._bootstrap[key] ?? defaultValue; + } + + stringVariation(key: string, defaultValue: string): string { + if (isServer) { + global.nodeSdk.stringVariation(key, this._ldContext, defaultValue).then(/* ignore */); + } + return this._bootstrap[key] ?? defaultValue; + } + + numberVariation(key: string, defaultValue: number): number { + if (isServer) { + global.nodeSdk.numberVariation(key, this._ldContext, defaultValue).then(/* ignore */); + } + return this._bootstrap[key] ?? defaultValue; + } + + jsonVariation(key: string, defaultValue: unknown): unknown { + if (isServer) { + global.nodeSdk.jsonVariation(key, this._ldContext, defaultValue).then(/* ignore */); + } + return this._bootstrap[key] ?? defaultValue; + } + variation(key: string, defaultValue?: LDFlagValue): LDFlagValue { if (isServer) { - // On the server during ssr, call variation for analytics purposes. global.nodeSdk.variation(key, this._ldContext, defaultValue).then(/* ignore */); } return this._bootstrap[key] ?? defaultValue; } + boolVariationDetail(key: string, defaultValue: boolean): LDEvaluationDetailTyped { + if (isServer) { + global.nodeSdk.boolVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); + } + + const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; + return { value: this._bootstrap[key], reason, variationIndex }; + } + + stringVariationDetail(key: string, defaultValue: string): LDEvaluationDetailTyped { + if (isServer) { + global.nodeSdk.stringVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); + } + + const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; + return { value: this._bootstrap[key], reason, variationIndex }; + } + + numberVariationDetail(key: string, defaultValue: number): LDEvaluationDetailTyped { + if (isServer) { + global.nodeSdk.numberVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); + } + + const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; + return { value: this._bootstrap[key], reason, variationIndex }; + } + + jsonVariationDetail(key: string, defaultValue: unknown): LDEvaluationDetailTyped { + if (isServer) { + global.nodeSdk.jsonVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); + } + + const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; + return { value: this._bootstrap[key], reason, variationIndex }; + } + variationDetail(key: string, defaultValue?: LDFlagValue): LDEvaluationDetail { if (isServer) { - // On the server during ssr, call variation for analytics purposes. global.nodeSdk.variationDetail(key, this._ldContext, defaultValue).then(/* ignore */); } diff --git a/packages/sdk/react-universal/src/server/hooks/variation/useVariationRsc.ts b/packages/sdk/react-universal/src/server/hooks/variation/useVariationRsc.ts index b8aacb94bb..5751ad23f6 100644 --- a/packages/sdk/react-universal/src/server/hooks/variation/useVariationRsc.ts +++ b/packages/sdk/react-universal/src/server/hooks/variation/useVariationRsc.ts @@ -2,11 +2,55 @@ import type { LDContext, LDFlagValue } from '@launchdarkly/node-server-sdk'; import { useLDClientRsc } from '../useLDClientRsc'; +export const useBoolVariationRsc = async (key: string, context: LDContext, def: boolean) => { + const ldc = await useLDClientRsc(context); + return ldc.boolVariation(key, def); +}; + +export const useStringVariationRsc = async (key: string, context: LDContext, def: string) => { + const ldc = await useLDClientRsc(context); + return ldc.stringVariation(key, def); +}; + +export const useNumberVariationRsc = async (key: string, context: LDContext, def: number) => { + const ldc = await useLDClientRsc(context); + return ldc.numberVariation(key, def); +}; + +export const useJsonVariationRsc = async (key: string, context: LDContext, def: undefined) => { + const ldc = await useLDClientRsc(context); + return ldc.jsonVariation(key, def); +}; + export const useVariationRsc = async (key: string, context: LDContext, def?: LDFlagValue) => { const ldc = await useLDClientRsc(context); return ldc.variation(key, def); }; +export const useBoolVariationDetailRsc = async (key: string, context: LDContext, def: boolean) => { + const ldc = await useLDClientRsc(context); + return ldc.boolVariationDetail(key, def); +}; + +export const useStringVariationDetailRsc = async (key: string, context: LDContext, def: string) => { + const ldc = await useLDClientRsc(context); + return ldc.stringVariationDetail(key, def); +}; + +export const useNumberVariationDetailRsc = async (key: string, context: LDContext, def: number) => { + const ldc = await useLDClientRsc(context); + return ldc.numberVariationDetail(key, def); +}; + +export const useJsonVariationDetailRsc = async ( + key: string, + context: LDContext, + def: undefined, +) => { + const ldc = await useLDClientRsc(context); + return ldc.jsonVariationDetail(key, def); +}; + export const useVariationDetailRsc = async (key: string, context: LDContext, def?: LDFlagValue) => { const ldc = await useLDClientRsc(context); return ldc.variationDetail(key, def); From 6ec07d156f96636b5246c6f9453b7f6bf13f78e8 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 12:42:33 -0500 Subject: [PATCH 04/10] update example --- .../example/app/components/helloClientComponent.tsx | 4 ++-- .../example/app/components/helloServerComponent.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sdk/react-universal/example/app/components/helloClientComponent.tsx b/packages/sdk/react-universal/example/app/components/helloClientComponent.tsx index 84bfeccce5..15ddeb73f8 100644 --- a/packages/sdk/react-universal/example/app/components/helloClientComponent.tsx +++ b/packages/sdk/react-universal/example/app/components/helloClientComponent.tsx @@ -1,11 +1,11 @@ 'use client'; -import { useVariationDetail } from '@launchdarkly/react-universal-sdk/client'; +import { useBoolVariationDetail } from '@launchdarkly/react-universal-sdk/client'; export default function HelloClientComponent() { // You need to set evaluationReasons to true when initializing the LDProvider to useVariationDetail. // Note: in the future evaluationReasons will be renamed withReasons. - const detail = useVariationDetail('my-boolean-flag-1'); + const detail = useBoolVariationDetail('my-boolean-flag-1', false); return (
diff --git a/packages/sdk/react-universal/example/app/components/helloServerComponent.tsx b/packages/sdk/react-universal/example/app/components/helloServerComponent.tsx index b56875d6cc..4655a8d670 100644 --- a/packages/sdk/react-universal/example/app/components/helloServerComponent.tsx +++ b/packages/sdk/react-universal/example/app/components/helloServerComponent.tsx @@ -1,9 +1,9 @@ import { getLDContext } from '@/app/utils'; -import { useVariationRsc } from '@launchdarkly/react-universal-sdk/server'; +import { useBoolVariationDetailRsc } from '@launchdarkly/react-universal-sdk/server'; export default async function HelloServerComponent() { - const flagValue = await useVariationRsc('my-boolean-flag-1', getLDContext()); + const flagValue = await useBoolVariationDetailRsc('my-boolean-flag-1', getLDContext(), false); return (
From 54ad065ed0859b7ceb2b05d58b1cf300bad80624 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 12:46:57 -0500 Subject: [PATCH 05/10] chore:create-release --- release-please-config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release-please-config.json b/release-please-config.json index d3530a025d..c5d9fc6e28 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -51,6 +51,9 @@ "packages/sdk/browser": { "bump-minor-pre-major": true }, + "packages/sdk/react-universal": { + "bump-minor-pre-major": true + }, "packages/sdk/server-ai": { "bump-minor-pre-major": true, "extra-files": [ From 7bb2b1868bf15cc144be6387663a696c5f400122 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 14:28:23 -0500 Subject: [PATCH 06/10] less redundant server client --- .../sdk/react-universal/src/ldClientRsc.ts | 120 +++++++++--------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/packages/sdk/react-universal/src/ldClientRsc.ts b/packages/sdk/react-universal/src/ldClientRsc.ts index df4427a468..fd7a605653 100644 --- a/packages/sdk/react-universal/src/ldClientRsc.ts +++ b/packages/sdk/react-universal/src/ldClientRsc.ts @@ -13,6 +13,12 @@ import type { JSSdk } from './types'; // Omit variationDetail because its return type is incompatible with js-core. type PartialJSSdk = Omit, 'variationDetail'>; +// Create a helper type for the variation methods +type VariationMethod = (key: string, defaultValue: T) => T; + +// Create a helper type for the variation detail methods +type VariationDetailMethod = (key: string, defaultValue: T) => LDEvaluationDetailTyped; + /** * A partial ldClient suitable for RSC and server side rendering. */ @@ -30,81 +36,77 @@ export class LDClientRsc implements PartialJSSdk { return this._ldContext; } - /** - * - * Call the server sdk variation for analytics purposes. - */ - boolVariation(key: string, defaultValue: boolean): boolean { - if (isServer) { - global.nodeSdk.boolVariation(key, this._ldContext, defaultValue).then(/* ignore */); - } - return this._bootstrap[key] ?? defaultValue; - } + private createVariation( + key: string, + defaultValue: T, + serverMethod: (key: string, context: LDContext, defaultValue: T) => Promise, + ): T { + serverMethod(key, this._ldContext, defaultValue).then(/* ignore */); - stringVariation(key: string, defaultValue: string): string { - if (isServer) { - global.nodeSdk.stringVariation(key, this._ldContext, defaultValue).then(/* ignore */); - } return this._bootstrap[key] ?? defaultValue; } - numberVariation(key: string, defaultValue: number): number { - if (isServer) { - global.nodeSdk.numberVariation(key, this._ldContext, defaultValue).then(/* ignore */); - } - return this._bootstrap[key] ?? defaultValue; - } - - jsonVariation(key: string, defaultValue: unknown): unknown { - if (isServer) { - global.nodeSdk.jsonVariation(key, this._ldContext, defaultValue).then(/* ignore */); - } - return this._bootstrap[key] ?? defaultValue; - } - - variation(key: string, defaultValue?: LDFlagValue): LDFlagValue { - if (isServer) { - global.nodeSdk.variation(key, this._ldContext, defaultValue).then(/* ignore */); - } - return this._bootstrap[key] ?? defaultValue; - } - - boolVariationDetail(key: string, defaultValue: boolean): LDEvaluationDetailTyped { - if (isServer) { - global.nodeSdk.boolVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); - } - + private createVariationDetail( + key: string, + defaultValue: T, + serverMethod: ( + key: string, + context: LDContext, + defaultValue: T, + ) => Promise>, + ): LDEvaluationDetailTyped { + serverMethod(key, this._ldContext, defaultValue).then(/* ignore */); const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; return { value: this._bootstrap[key], reason, variationIndex }; } - stringVariationDetail(key: string, defaultValue: string): LDEvaluationDetailTyped { - if (isServer) { - global.nodeSdk.stringVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); - } + boolVariation: VariationMethod = (key, defaultValue) => + this.createVariation(key, defaultValue, global.nodeSdk.boolVariation.bind(global.nodeSdk)); - const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; - return { value: this._bootstrap[key], reason, variationIndex }; - } + stringVariation: VariationMethod = (key, defaultValue) => + this.createVariation(key, defaultValue, global.nodeSdk.stringVariation.bind(global.nodeSdk)); - numberVariationDetail(key: string, defaultValue: number): LDEvaluationDetailTyped { - if (isServer) { - global.nodeSdk.numberVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); - } + numberVariation: VariationMethod = (key, defaultValue) => + this.createVariation(key, defaultValue, global.nodeSdk.numberVariation.bind(global.nodeSdk)); - const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; - return { value: this._bootstrap[key], reason, variationIndex }; - } + jsonVariation: VariationMethod = (key, defaultValue) => + this.createVariation(key, defaultValue, global.nodeSdk.jsonVariation.bind(global.nodeSdk)); - jsonVariationDetail(key: string, defaultValue: unknown): LDEvaluationDetailTyped { + variation(key: string, defaultValue?: LDFlagValue): LDFlagValue { if (isServer) { - global.nodeSdk.jsonVariationDetail(key, this._ldContext, defaultValue).then(/* ignore */); + global.nodeSdk.variation(key, this._ldContext, defaultValue).then(/* ignore */); } - - const { reason, variation: variationIndex } = this._bootstrap.$flagsState[key]; - return { value: this._bootstrap[key], reason, variationIndex }; + return this._bootstrap[key] ?? defaultValue; } + boolVariationDetail: VariationDetailMethod = (key, defaultValue) => + this.createVariationDetail( + key, + defaultValue, + global.nodeSdk.boolVariationDetail.bind(global.nodeSdk), + ); + + stringVariationDetail: VariationDetailMethod = (key, defaultValue) => + this.createVariationDetail( + key, + defaultValue, + global.nodeSdk.stringVariationDetail.bind(global.nodeSdk), + ); + + numberVariationDetail: VariationDetailMethod = (key, defaultValue) => + this.createVariationDetail( + key, + defaultValue, + global.nodeSdk.numberVariationDetail.bind(global.nodeSdk), + ); + + jsonVariationDetail: VariationDetailMethod = (key, defaultValue) => + this.createVariationDetail( + key, + defaultValue, + global.nodeSdk.jsonVariationDetail.bind(global.nodeSdk), + ); + variationDetail(key: string, defaultValue?: LDFlagValue): LDEvaluationDetail { if (isServer) { global.nodeSdk.variationDetail(key, this._ldContext, defaultValue).then(/* ignore */); From 85b3f567b9ee9b027e7481e118b5cbb3e869b463 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 16:35:45 -0500 Subject: [PATCH 07/10] can run immediately --- packages/sdk/react-universal/src/client/LDProvider.tsx | 3 ++- packages/sdk/react-universal/src/client/setupListeners.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/sdk/react-universal/src/client/LDProvider.tsx b/packages/sdk/react-universal/src/client/LDProvider.tsx index 230d9012bd..559378ee4a 100644 --- a/packages/sdk/react-universal/src/client/LDProvider.tsx +++ b/packages/sdk/react-universal/src/client/LDProvider.tsx @@ -38,6 +38,8 @@ export const LDProvider = ({ let jsSdk: JSSdk = undefined as any; if (!isServer) { jsSdk = initialize(clientSideID ?? '', options); + // When bootstrap is passed in, identify runs immediately + jsSdk.identify(context, { bootstrap }); } const [state, setState] = useState({ @@ -48,7 +50,6 @@ export const LDProvider = ({ useEffect(() => { setupListeners(setState, jsSdk); - jsSdk.identify(context, { bootstrap }); }, []); return {children}; diff --git a/packages/sdk/react-universal/src/client/setupListeners.ts b/packages/sdk/react-universal/src/client/setupListeners.ts index 04a18749a8..c24d5c49ed 100644 --- a/packages/sdk/react-universal/src/client/setupListeners.ts +++ b/packages/sdk/react-universal/src/client/setupListeners.ts @@ -7,4 +7,7 @@ export const setupListeners = (setState: Dispatch>, jsSdk.on('change', () => { setState((prevState) => ({ ...prevState, jsSdk })); }); + jsSdk.on('ready', () => { + setState((prevState) => ({ ...prevState, jsSdk })); + }); }; From 388b7e784fab20f57c467f7afb9ce3a4dc7e8f04 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 16:43:49 -0500 Subject: [PATCH 08/10] await this --- packages/sdk/react-universal/src/client/LDProvider.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/sdk/react-universal/src/client/LDProvider.tsx b/packages/sdk/react-universal/src/client/LDProvider.tsx index 559378ee4a..7666a331d7 100644 --- a/packages/sdk/react-universal/src/client/LDProvider.tsx +++ b/packages/sdk/react-universal/src/client/LDProvider.tsx @@ -39,7 +39,9 @@ export const LDProvider = ({ if (!isServer) { jsSdk = initialize(clientSideID ?? '', options); // When bootstrap is passed in, identify runs immediately - jsSdk.identify(context, { bootstrap }); + (async () => { + await jsSdk.identify(context, { bootstrap }); + })(); } const [state, setState] = useState({ From ef56fe016b5a5f431936f9b45c03789c6ea33a00 Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Wed, 12 Feb 2025 16:52:26 -0500 Subject: [PATCH 09/10] cleaned up --- packages/sdk/react-universal/src/client/LDProvider.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/sdk/react-universal/src/client/LDProvider.tsx b/packages/sdk/react-universal/src/client/LDProvider.tsx index 7666a331d7..e9f23b587c 100644 --- a/packages/sdk/react-universal/src/client/LDProvider.tsx +++ b/packages/sdk/react-universal/src/client/LDProvider.tsx @@ -38,10 +38,7 @@ export const LDProvider = ({ let jsSdk: JSSdk = undefined as any; if (!isServer) { jsSdk = initialize(clientSideID ?? '', options); - // When bootstrap is passed in, identify runs immediately - (async () => { - await jsSdk.identify(context, { bootstrap }); - })(); + jsSdk.identify(context, { bootstrap }); } const [state, setState] = useState({ From c8ec741d8f264c70604818065cb03ecdf31ba06b Mon Sep 17 00:00:00 2001 From: Michael Anderjaska Date: Thu, 13 Feb 2025 10:21:39 -0500 Subject: [PATCH 10/10] should lint --- .../sdk/react-universal/src/ldClientRsc.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/sdk/react-universal/src/ldClientRsc.ts b/packages/sdk/react-universal/src/ldClientRsc.ts index fd7a605653..781306633f 100644 --- a/packages/sdk/react-universal/src/ldClientRsc.ts +++ b/packages/sdk/react-universal/src/ldClientRsc.ts @@ -36,7 +36,7 @@ export class LDClientRsc implements PartialJSSdk { return this._ldContext; } - private createVariation( + private _createVariation( key: string, defaultValue: T, serverMethod: (key: string, context: LDContext, defaultValue: T) => Promise, @@ -46,7 +46,7 @@ export class LDClientRsc implements PartialJSSdk { return this._bootstrap[key] ?? defaultValue; } - private createVariationDetail( + private _createVariationDetail( key: string, defaultValue: T, serverMethod: ( @@ -61,16 +61,16 @@ export class LDClientRsc implements PartialJSSdk { } boolVariation: VariationMethod = (key, defaultValue) => - this.createVariation(key, defaultValue, global.nodeSdk.boolVariation.bind(global.nodeSdk)); + this._createVariation(key, defaultValue, global.nodeSdk.boolVariation.bind(global.nodeSdk)); stringVariation: VariationMethod = (key, defaultValue) => - this.createVariation(key, defaultValue, global.nodeSdk.stringVariation.bind(global.nodeSdk)); + this._createVariation(key, defaultValue, global.nodeSdk.stringVariation.bind(global.nodeSdk)); numberVariation: VariationMethod = (key, defaultValue) => - this.createVariation(key, defaultValue, global.nodeSdk.numberVariation.bind(global.nodeSdk)); + this._createVariation(key, defaultValue, global.nodeSdk.numberVariation.bind(global.nodeSdk)); jsonVariation: VariationMethod = (key, defaultValue) => - this.createVariation(key, defaultValue, global.nodeSdk.jsonVariation.bind(global.nodeSdk)); + this._createVariation(key, defaultValue, global.nodeSdk.jsonVariation.bind(global.nodeSdk)); variation(key: string, defaultValue?: LDFlagValue): LDFlagValue { if (isServer) { @@ -80,28 +80,28 @@ export class LDClientRsc implements PartialJSSdk { } boolVariationDetail: VariationDetailMethod = (key, defaultValue) => - this.createVariationDetail( + this._createVariationDetail( key, defaultValue, global.nodeSdk.boolVariationDetail.bind(global.nodeSdk), ); stringVariationDetail: VariationDetailMethod = (key, defaultValue) => - this.createVariationDetail( + this._createVariationDetail( key, defaultValue, global.nodeSdk.stringVariationDetail.bind(global.nodeSdk), ); numberVariationDetail: VariationDetailMethod = (key, defaultValue) => - this.createVariationDetail( + this._createVariationDetail( key, defaultValue, global.nodeSdk.numberVariationDetail.bind(global.nodeSdk), ); jsonVariationDetail: VariationDetailMethod = (key, defaultValue) => - this.createVariationDetail( + this._createVariationDetail( key, defaultValue, global.nodeSdk.jsonVariationDetail.bind(global.nodeSdk),