Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/react-native-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reflag/react-native-sdk",
"version": "0.1.3",
"version": "0.1.4",
"license": "MIT",
"repository": {
"type": "git",
Expand Down Expand Up @@ -32,7 +32,7 @@
},
"dependencies": {
"@react-native-async-storage/async-storage": "^2.2.0",
"@reflag/react-sdk": "1.4.3"
"@reflag/react-sdk": "1.4.4"
},
"peerDependencies": {
"react": "*",
Expand Down
3 changes: 2 additions & 1 deletion packages/react-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,8 @@ The `<ReflagProvider>` initializes the Reflag SDK, fetches flags and starts list
- `apiBaseUrl`: Optional base URL for the Reflag API. Use this to override the default API endpoint,
- `appBaseUrl`: Optional base URL for the Reflag application. Use this to override the default app URL,
- `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint,
- `debug`: Set to `true` to enable debug logging to the console,
- `logger`: Optional custom logger implementation (`debug`, `info`, `warn`, `error`) used by the underlying client,
- `debug`: Set to `true` to enable debug logging to the console. If both `logger` and `debug` are provided, `logger` takes precedence,
- `toolbar`: Optional [configuration](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for the Reflag toolbar,
- `feedback`: Optional configuration for feedback collection

Expand Down
2 changes: 1 addition & 1 deletion packages/react-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reflag/react-sdk",
"version": "1.4.3",
"version": "1.4.4",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
63 changes: 41 additions & 22 deletions packages/react-sdk/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
CompanyContext,
HookArgs,
InitOptions,
Logger,
RawFlag,
ReflagClient,
ReflagContext,
Expand Down Expand Up @@ -152,6 +153,13 @@ export type ReflagPropsBase = {
*/
initialLoading?: boolean;

/**
* A custom logger to use for SDK logs.
* Use this for advanced control or filtering of SDK logs.
* If both `logger` and `debug` are provided, `logger` takes precedence.
*/
logger?: Logger;

/**
* Set to `true` to enable debug logging to the console,
*/
Expand All @@ -164,7 +172,7 @@ export type ReflagPropsBase = {
*/
export type ReflagInitOptionsBase = Omit<
InitOptions,
"user" | "company" | "other" | "otherContext" | "bootstrappedFlags"
"user" | "company" | "other" | "otherContext" | "bootstrappedFlags" | "logger"
>;

/**
Expand All @@ -178,20 +186,28 @@ const reflagClients = new Map<string, ReflagClient>();
* Only creates a new ReflagClient is not already created or if it hook is run on the server.
* @internal
*/
function useReflagClient(initOptions: InitOptions, debug = false) {
function useReflagClient(initOptions: InitOptions & { debug?: boolean }) {
const {
debug = false,
logger,
publishableKey,
sdkVersion,
...clientOptions
} = initOptions;
const isServer = typeof window === "undefined";
if (isServer || !reflagClients.has(initOptions.publishableKey)) {
if (isServer || !reflagClients.has(publishableKey)) {
const client = new ReflagClient({
...initOptions,
logger: debug ? console : undefined,
sdkVersion: initOptions.sdkVersion ?? SDK_VERSION,
...clientOptions,
publishableKey,
logger: logger ?? (debug ? console : undefined),
sdkVersion: sdkVersion ?? SDK_VERSION,
});
if (!isServer) {
reflagClients.set(initOptions.publishableKey, client);
reflagClients.set(publishableKey, client);
}
return client;
}
return reflagClients.get(initOptions.publishableKey)!;
return reflagClients.get(publishableKey)!;
}

type ProviderContextType = {
Expand All @@ -204,7 +220,10 @@ const ProviderContext = createContext<ProviderContextType | null>(null);
/**
* Props for the ReflagClientProvider.
*/
export type ReflagClientProviderProps = Omit<ReflagPropsBase, "debug"> & {
export type ReflagClientProviderProps = Omit<
ReflagPropsBase,
"debug" | "logger"
> & {
client: ReflagClient;
};

Expand Down Expand Up @@ -282,20 +301,20 @@ export function ReflagProvider({
otherContext,
loadingComponent,
initialLoading = true,
logger,
debug,
...config
}: ReflagProps) {
const resolvedContext = useMemo(
() => ({ user, company, other: otherContext, ...context }),
[user, company, otherContext, context],
);
const client = useReflagClient(
{
...config,
...resolvedContext,
},
const client = useReflagClient({
...config,
...resolvedContext,
debug,
);
logger,
});

// Initialize the client if it is not already initialized
useEffect(() => {
Expand Down Expand Up @@ -340,17 +359,17 @@ export function ReflagBootstrappedProvider({
children,
loadingComponent,
initialLoading = false,
logger,
debug,
...config
}: ReflagBootstrappedProps) {
const client = useReflagClient(
{
...config,
...flags.context,
bootstrappedFlags: flags.flags,
},
const client = useReflagClient({
...config,
...flags.context,
bootstrappedFlags: flags.flags,
debug,
);
logger,
});

// Initialize the client if it is not already initialized
useEffect(() => {
Expand Down
38 changes: 38 additions & 0 deletions packages/react-sdk/test/usage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,44 @@ describe("<ReflagProvider />", () => {
});
});

test("uses provided logger", async () => {
const logger = {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
};

const { result, unmount } = renderHook(() => useClient(), {
wrapper: ({ children }) => getProvider({ children, logger }),
});

await waitFor(() => {
expect(result.current.logger).toBe(logger);
});

unmount();
});

test("prefers logger over debug mode", async () => {
const logger = {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
};

const { result, unmount } = renderHook(() => useClient(), {
wrapper: ({ children }) => getProvider({ children, logger, debug: true }),
});

await waitFor(() => {
expect(result.current.logger).toBe(logger);
});

unmount();
});

test("only calls init once with the same args", () => {
const node = getProvider();
const initialize = vi.spyOn(ReflagClient.prototype, "initialize");
Expand Down
3 changes: 2 additions & 1 deletion packages/vue-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ The `<ReflagProvider>` initializes the Reflag SDK, fetches flags and starts list
- `apiBaseUrl`: Optional base URL for the Reflag API. Use this to override the default API endpoint,
- `appBaseUrl`: Optional base URL for the Reflag application. Use this to override the default app URL,
- `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint,
- `debug`: Set to `true` to enable debug logging to the console,
- `debug`: Set to `true` to enable debug logging to the console. If both `logger` and `debug` are provided, `logger` takes precedence,
- `logger`: Optional custom logger implementation (`debug`, `info`, `warn`, `error`) used by the underlying client,
- `toolbar`: Optional [configuration](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for the Reflag toolbar,
- `feedback`: Optional configuration for feedback collection

Expand Down
2 changes: 1 addition & 1 deletion packages/vue-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@reflag/vue-sdk",
"version": "1.3.1",
"version": "1.3.2",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
16 changes: 8 additions & 8 deletions packages/vue-sdk/src/ReflagBootstrappedProvider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ const {
flags,
initialLoading = false,
enableTracking = true,
logger,
debug,
...config
} = defineProps<ReflagBootstrappedProps>();

const client = useReflagClient(
{
...config,
...flags?.context,
enableTracking,
bootstrappedFlags: flags?.flags,
},
const client = useReflagClient({
...config,
...flags?.context,
enableTracking,
bootstrappedFlags: flags?.flags,
debug,
);
logger,
});

const isLoading = ref(
client.getState() !== "initialized" ? initialLoading : false,
Expand Down
14 changes: 7 additions & 7 deletions packages/vue-sdk/src/ReflagProvider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
otherContext,
initialLoading = true,
enableTracking = true,
logger,
debug,
...config
} = defineProps<ReflagProps>();
Expand All @@ -25,14 +26,13 @@ const resolvedContext = computed(() => ({
...context,
}));

const client = useReflagClient(
{
...config,
...resolvedContext.value,
enableTracking,
},
const client = useReflagClient({
...config,
...resolvedContext.value,
enableTracking,
debug,
);
logger,
});

const isLoading = ref(
client.getState() !== "initialized" ? initialLoading : false,
Expand Down
20 changes: 13 additions & 7 deletions packages/vue-sdk/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,28 @@ const reflagClients = new Map<string, ReflagClient>();
* @internal
*/
export function useReflagClient(
initOptions: InitOptions,
debug = false,
initOptions: InitOptions & { debug?: boolean },
): ReflagClient {
const {
debug = false,
logger,
publishableKey,
...clientOptions
} = initOptions;
const isServer = typeof window === "undefined";
if (isServer || !reflagClients.has(initOptions.publishableKey)) {
if (isServer || !reflagClients.has(publishableKey)) {
const client = new ReflagClient({
...initOptions,
...clientOptions,
publishableKey,
sdkVersion: SDK_VERSION,
logger: debug ? console : undefined,
logger: logger ?? (debug ? console : undefined),
});
if (!isServer) {
reflagClients.set(initOptions.publishableKey, client);
reflagClients.set(publishableKey, client);
}
return client;
}
return reflagClients.get(initOptions.publishableKey)!;
return reflagClients.get(publishableKey)!;
}

/**
Expand Down
15 changes: 13 additions & 2 deletions packages/vue-sdk/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Ref } from "vue";
import type {
CompanyContext,
InitOptions,
Logger,
RawFlags,
ReflagClient,
ReflagContext,
Expand Down Expand Up @@ -70,7 +71,7 @@ export type RequestFlagFeedbackOptions = Omit<
*/
export type ReflagInitOptionsBase = Omit<
InitOptions,
"user" | "company" | "other" | "otherContext" | "bootstrappedFlags"
"user" | "company" | "other" | "otherContext" | "bootstrappedFlags" | "logger"
>;

/**
Expand All @@ -83,6 +84,13 @@ export type ReflagBaseProps = {
*/
initialLoading?: boolean;

/**
* A custom logger to use for SDK logs.
* Use this for advanced control or filtering of SDK logs.
* If both `logger` and `debug` are provided, `logger` takes precedence.
*/
logger?: Logger;

/**
* Set to `true` to enable debug logging to the console.
*/
Expand All @@ -92,7 +100,10 @@ export type ReflagBaseProps = {
/**
* Props for the ReflagClientProvider.
*/
export type ReflagClientProviderProps = Omit<ReflagBaseProps, "debug"> & {
export type ReflagClientProviderProps = Omit<
ReflagBaseProps,
"debug" | "logger"
> & {
/**
* A pre-initialized ReflagClient to use.
*/
Expand Down
Loading