Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { translateTrackingEventDetails } from './translateTrackingEventDetails';
/**
* Create a ResolutionDetails for an evaluation that produced a type different
* than the expected type.
* @param value The default value to populate the ResolutionDetails with.
* @returns A ResolutionDetails with the default value.
*/
function wrongTypeResult<T>(value: T): ResolutionDetails<T> {
return {
Expand Down Expand Up @@ -56,10 +58,22 @@ export interface BaseProviderConfig {
export abstract class BaseOpenFeatureProvider<
TClient extends OpenFeatureLDClientContract = OpenFeatureLDClientContract,
> implements Provider {
/**
* Metadata reported to OpenFeature. The provider name is supplied by each
* concrete subclass via the {@link BaseProviderConfig.providerName} field.
*/
readonly metadata: ProviderMetadata;

/**
* The OpenFeature paradigm this provider runs on. LaunchDarkly server-side
* SDKs always run on the server.
*/
readonly runsOn: Paradigm = 'server';

/**
* Event emitter used to surface OpenFeature provider events such as
* {@link ProviderEvents.ConfigurationChanged}.
*/
readonly events = new OpenFeatureEventEmitter();

private _client?: TClient;
Expand Down Expand Up @@ -102,6 +116,11 @@ export abstract class BaseOpenFeatureProvider<
});
}

/**
* Called by OpenFeature once the provider is registered. Waits for the
* underlying LDClient to finish initialization, or rethrows the error that
* was captured if client construction failed.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async initialize(context?: EvaluationContext): Promise<void> {
if (!this._client) {
Expand All @@ -113,6 +132,19 @@ export abstract class BaseOpenFeatureProvider<
await this._client.waitForInitialization({ timeout: this._initTimeoutSeconds });
}

/**
* Determines the boolean variation of a feature flag for a context, along with information about
* how it was calculated.
*
* If the flag does not evaluate to a boolean value, then the defaultValue will be returned.
*
* @param flagKey The unique key of the feature flag.
* @param defaultValue The default value of the flag, to be used if the value is not available
* from LaunchDarkly.
* @param context The context requesting the flag. The client will generate an analytics event to
* register this context with LaunchDarkly if the context does not already exist.
* @returns A promise which will resolve to a ResolutionDetails.
*/
async resolveBooleanEvaluation(
flagKey: string,
defaultValue: boolean,
Expand All @@ -129,6 +161,19 @@ export abstract class BaseOpenFeatureProvider<
return wrongTypeResult(defaultValue);
}

/**
* Determines the string variation of a feature flag for a context, along with information about
* how it was calculated.
*
* If the flag does not evaluate to a string value, then the defaultValue will be returned.
*
* @param flagKey The unique key of the feature flag.
* @param defaultValue The default value of the flag, to be used if the value is not available
* from LaunchDarkly.
* @param context The context requesting the flag. The client will generate an analytics event to
* register this context with LaunchDarkly if the context does not already exist.
* @returns A promise which will resolve to a ResolutionDetails.
*/
async resolveStringEvaluation(
flagKey: string,
defaultValue: string,
Expand All @@ -145,6 +190,19 @@ export abstract class BaseOpenFeatureProvider<
return wrongTypeResult(defaultValue);
}

/**
* Determines the numeric variation of a feature flag for a context, along with information about
* how it was calculated.
*
* If the flag does not evaluate to a numeric value, then the defaultValue will be returned.
*
* @param flagKey The unique key of the feature flag.
* @param defaultValue The default value of the flag, to be used if the value is not available
* from LaunchDarkly.
* @param context The context requesting the flag. The client will generate an analytics event to
* register this context with LaunchDarkly if the context does not already exist.
* @returns A promise which will resolve to a ResolutionDetails.
*/
async resolveNumberEvaluation(
flagKey: string,
defaultValue: number,
Expand All @@ -161,6 +219,19 @@ export abstract class BaseOpenFeatureProvider<
return wrongTypeResult(defaultValue);
}

/**
* Determines the object variation of a feature flag for a context, along with information about
* how it was calculated.
*
* If the flag does not evaluate to a JSON object value, then the defaultValue will be returned.
*
* @param flagKey The unique key of the feature flag.
* @param defaultValue The default value of the flag, to be used if the value is not available
* from LaunchDarkly.
* @param context The context requesting the flag. The client will generate an analytics event to
* register this context with LaunchDarkly if the context does not already exist.
* @returns A promise which will resolve to a ResolutionDetails.
*/
async resolveObjectEvaluation<U extends JsonValue>(
flagKey: string,
defaultValue: U,
Expand All @@ -177,14 +248,28 @@ export abstract class BaseOpenFeatureProvider<
return wrongTypeResult<U>(defaultValue);
}

/**
* Returns the OpenFeature hooks registered for this provider. The
* LaunchDarkly provider does not currently register any provider-level
* hooks, so this always returns an empty array.
*/
get hooks(): Hook[] {
return [];
}

/**
* Get the LDClient instance used by this provider.
*
* @returns The client for this provider.
*/
getClient(): TClient {
return this._client!;
}

/**
* Called by OpenFeature when it needs to close the provider. This will flush
* events from the LDClient and then close it.
*/
async onClose(): Promise<void> {
try {
await this._client?.flush();
Expand All @@ -193,6 +278,13 @@ export abstract class BaseOpenFeatureProvider<
}
}

/**
* Track a user action or application state, usually representing a business objective or outcome.
* @param trackingEventName The name of the event, which may correspond to a metric
* in Experimentation.
* @param context The context to track.
* @param trackingEventDetails Optional additional information to associate with the event.
*/
track(
trackingEventName: string,
context: EvaluationContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,49 @@ import type { LDContext, LDEvaluationDetail, LDFlagValue } from '@launchdarkly/j
* Any LaunchDarkly server-side LDClient should satisfy this interface.
*/
export interface OpenFeatureLDClientContract {
/**
* Evaluate a flag and return the value along with details of how it was
* calculated.
*
* @param key The unique key of the feature flag.
* @param context The context to evaluate the flag against.
* @param defaultValue The value to return if the flag cannot be evaluated.
* @returns A promise which resolves to the evaluation detail.
*/
variationDetail(
key: string,
context: LDContext,
defaultValue: LDFlagValue,
): Promise<LDEvaluationDetail>;

/**
* Wait for the underlying client to finish initialization.
*
* @param options Optional initialization options. The `timeout` field is
* the maximum number of seconds to wait.
*/
waitForInitialization(options?: { timeout: number }): Promise<unknown>;

/**
* Flush any pending analytics events to LaunchDarkly. Called by the provider
* during {@link Provider.onClose}.
*/
flush(): Promise<void>;

/**
* Shut down the client and release any resources it holds. Called by the
* provider during {@link Provider.onClose} after {@link flush}.
*/
close(): void;

/**
* Track a custom event for the given context.
*
* @param key The name of the event.
* @param context The context to associate with the event.
* @param data Optional additional information to attach to the event.
* @param metricValue Optional numeric metric value to associate with the
* event.
*/
track(key: string, context: LDContext, data?: any, metricValue?: number): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ function translateContextCommon(

/**
* Convert an OpenFeature evaluation context into an LDContext.
* @param logger Logger to use when warnings or errors are encountered during translation.
* @param evalContext The OpenFeature evaluation context to translate.
* @returns An LDContext based on the evaluation context.
*/
Expand Down
Loading