Skip to content

Commit

Permalink
refactor: export public option types (#1101)
Browse files Browse the repository at this point in the history
## This PR

- renames the `shared` folder to `internal` to prevent accident exports
- export public option types

### Notes

This will make it easier for devs who need access to the option types.

---------

Signed-off-by: Michael Beemer <[email protected]>
  • Loading branch information
beeme1mr authored Dec 10, 2024
1 parent e335615 commit 16321c3
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 102 deletions.
83 changes: 0 additions & 83 deletions packages/react/src/common/options.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/react/src/context/use-context-mutator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useContext, useRef } from 'react';
import type { EvaluationContext } from '@openfeature/web-sdk';
import { OpenFeature } from '@openfeature/web-sdk';
import { Context } from '../common';
import { Context } from '../internal';

export type ContextMutationOptions = {
/**
Expand Down
11 changes: 4 additions & 7 deletions packages/react/src/evaluation/use-feature-flag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
ProviderStatus,
} from '@openfeature/web-sdk';
import { useEffect, useRef, useState } from 'react';
import type { ReactFlagEvaluationOptions} from '../common';
import { DEFAULT_OPTIONS, isEqual, normalizeOptions, suspendUntilReady, useProviderOptions } from '../common';
import type { ReactFlagEvaluationNoSuspenseOptions, ReactFlagEvaluationOptions } from '../options';
import { DEFAULT_OPTIONS, isEqual, normalizeOptions, suspendUntilReady, useProviderOptions } from '../internal';
import { useOpenFeatureClient } from '../provider/use-open-feature-client';
import { useOpenFeatureClientStatus } from '../provider/use-open-feature-client-status';
import type { FlagQuery } from '../query';
Expand All @@ -33,9 +33,6 @@ type ConstrainedFlagQuery<T> = FlagQuery<
: JsonValue
>;

// suspense options removed for the useSuspenseFlag hooks
type NoSuspenseOptions = Omit<ReactFlagEvaluationOptions, 'suspend' | 'suspendUntilReady' | 'suspendWhileReconciling'>;

/**
* Evaluates a feature flag generically, returning an react-flavored queryable object.
* The resolver method to use is based on the type of the defaultValue.
Expand Down Expand Up @@ -84,13 +81,13 @@ type UseFlagReturn<T extends FlagValue> = ReturnType<typeof useFlag<T>>;
* @param {string} flagKey the flag identifier
* @template {FlagValue} T A optional generic argument constraining the default.
* @param {T} defaultValue the default value; used to determine what resolved type should be used.
* @param {NoSuspenseOptions} options for this evaluation
* @param {ReactFlagEvaluationNoSuspenseOptions} options for this evaluation
* @returns { UseFlagReturn<T> } a queryable object containing useful information about the flag.
*/
export function useSuspenseFlag<T extends FlagValue = FlagValue>(
flagKey: string,
defaultValue: T,
options?: NoSuspenseOptions,
options?: ReactFlagEvaluationNoSuspenseOptions,
): UseFlagReturn<T> {
return useFlag(flagKey, defaultValue, { ...options, suspendUntilReady: true, suspendWhileReconciling: true });
}
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './query';
export * from './provider';
export * from './context';
export * from './tracking';
export * from './options';
// re-export the web-sdk so consumers can access that API from the react-sdk
export * from '@openfeature/web-sdk';
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import type { Client } from '@openfeature/web-sdk';
import React from 'react';
import type { NormalizedOptions, ReactFlagEvaluationOptions} from '../common';
import { normalizeOptions } from '../common';
import type { NormalizedOptions, ReactFlagEvaluationOptions } from '../options';
import { normalizeOptions } from '.';

/**
* The underlying React context.
* DO NOT EXPORT PUBLICLY
* @internal
*/
export const Context = React.createContext<{ client: Client; domain?: string; options: ReactFlagEvaluationOptions } | undefined>(undefined);
export const Context = React.createContext<
{ client: Client; domain?: string; options: ReactFlagEvaluationOptions } | undefined
>(undefined);

/**
* Get a normalized copy of the options used for this OpenFeatureProvider, see {@link normalizeOptions}.
Expand Down
File renamed without changes.
File renamed without changes.
40 changes: 40 additions & 0 deletions packages/react/src/internal/options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { ReactFlagEvaluationOptions, NormalizedOptions } from '../options';

/**
* Default options.
* DO NOT EXPORT PUBLICLY
* @internal
*/
export const DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {
updateOnContextChanged: true,
updateOnConfigurationChanged: true,
suspendUntilReady: false,
suspendWhileReconciling: false,
};

/**
* Returns normalization options (all `undefined` fields removed, and `suspend` decomposed to `suspendUntilReady` and `suspendWhileReconciling`).
* DO NOT EXPORT PUBLICLY
* @internal
* @param {ReactFlagEvaluationOptions} options options to normalize
* @returns {NormalizedOptions} normalized options
*/
export const normalizeOptions: (options?: ReactFlagEvaluationOptions) => NormalizedOptions = (
options: ReactFlagEvaluationOptions = {},
) => {
const updateOnContextChanged = options.updateOnContextChanged;
const updateOnConfigurationChanged = options.updateOnConfigurationChanged;

// fall-back the suspense options to the catch-all `suspend` property
const suspendUntilReady = 'suspendUntilReady' in options ? options.suspendUntilReady : options.suspend;
const suspendWhileReconciling =
'suspendWhileReconciling' in options ? options.suspendWhileReconciling : options.suspend;

return {
// only return these if properly set (no undefined to allow overriding with spread)
...(typeof suspendUntilReady === 'boolean' && { suspendUntilReady }),
...(typeof suspendWhileReconciling === 'boolean' && { suspendWhileReconciling }),
...(typeof updateOnContextChanged === 'boolean' && { updateOnContextChanged }),
...(typeof updateOnConfigurationChanged === 'boolean' && { updateOnConfigurationChanged }),
};
};
File renamed without changes.
53 changes: 53 additions & 0 deletions packages/react/src/options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { FlagEvaluationOptions } from '@openfeature/web-sdk';

export type ReactFlagEvaluationOptions = (
| {
/**
* Enable or disable all suspense functionality.
* Cannot be used in conjunction with `suspendUntilReady` and `suspendWhileReconciling` options.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspend?: boolean;
suspendUntilReady?: never;
suspendWhileReconciling?: never;
}
| {
/**
* Suspend flag evaluations while the provider is not ready.
* Set to false if you don't want to show suspense fallbacks until the provider is initialized.
* Defaults to false.
* Cannot be used in conjunction with `suspend` option.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspendUntilReady?: boolean;
/**
* Suspend flag evaluations while the provider's context is being reconciled.
* Set to true if you want to show suspense fallbacks while flags are re-evaluated after context changes.
* Defaults to false.
* Cannot be used in conjunction with `suspend` option.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspendWhileReconciling?: boolean;
suspend?: never;
}
) & {
/**
* Update the component if the provider emits a ConfigurationChanged event.
* Set to false to prevent components from re-rendering when flag value changes
* are received by the associated provider.
* Defaults to true.
*/
updateOnConfigurationChanged?: boolean;
/**
* Update the component when the OpenFeature context changes.
* Set to false to prevent components from re-rendering when attributes which
* may be factors in flag evaluation change.
* Defaults to true.
*/
updateOnContextChanged?: boolean;
} & FlagEvaluationOptions;

// suspense options removed for the useSuspenseFlag hooks
export type ReactFlagEvaluationNoSuspenseOptions = Omit<ReactFlagEvaluationOptions, 'suspend' | 'suspendUntilReady' | 'suspendWhileReconciling'>;

export type NormalizedOptions = Omit<ReactFlagEvaluationOptions, 'suspend'>;
4 changes: 2 additions & 2 deletions packages/react/src/provider/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Client} from '@openfeature/web-sdk';
import { OpenFeature } from '@openfeature/web-sdk';
import * as React from 'react';
import type { ReactFlagEvaluationOptions } from '../common';
import { Context } from '../common';
import type { ReactFlagEvaluationOptions } from '../options';
import { Context } from '../internal';

type ClientOrDomain =
| {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/provider/test-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
OpenFeature
} from '@openfeature/web-sdk';
import React from 'react';
import type { NormalizedOptions } from '../common';
import type { NormalizedOptions } from '../options';
import { OpenFeatureProvider } from './provider';

type FlagValueMap = { [flagKey: string]: JsonValue };
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/provider/use-open-feature-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Context } from '../common';
import { Context } from '../internal';
import type { Client } from '@openfeature/web-sdk';

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/provider/use-when-provider-ready.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ProviderStatus } from '@openfeature/web-sdk';
import { useOpenFeatureClient } from './use-open-feature-client';
import { useOpenFeatureClientStatus } from './use-open-feature-client-status';
import type { ReactFlagEvaluationOptions} from '../common';
import { DEFAULT_OPTIONS, useProviderOptions, normalizeOptions, suspendUntilReady } from '../common';
import type { ReactFlagEvaluationOptions } from '../options';
import { DEFAULT_OPTIONS, useProviderOptions, normalizeOptions, suspendUntilReady } from '../internal';

type Options = Pick<ReactFlagEvaluationOptions, 'suspendUntilReady'>;

Expand Down
2 changes: 1 addition & 1 deletion packages/react/test/is-equal.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isEqual } from '../src/common/is-equal';
import { isEqual } from '../src/internal/is-equal';

describe('isEqual', () => {
it('should return true for equal primitive values', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/test/options.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { normalizeOptions } from '../src/common/options';
import { normalizeOptions } from '../src/internal/options';

describe('normalizeOptions', () => {
// we spread results from this function, so we never want to return null
Expand Down

0 comments on commit 16321c3

Please sign in to comment.