diff --git a/packages/optimizely-sdk/lib/core/decision_service/index.d.ts b/packages/optimizely-sdk/lib/core/decision_service/index.d.ts new file mode 100644 index 000000000..0daf24b22 --- /dev/null +++ b/packages/optimizely-sdk/lib/core/decision_service/index.d.ts @@ -0,0 +1,107 @@ +/** + * Copyright 2020, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare module '@optimizely/optimizely-sdk/lib/core/decision_service' { + import { LogHandler } from '@optimizely/js-sdk-logging'; + import { ProjectConfig } from '@optimizely/optimizely-sdk/lib/core/project_config'; + + /** + * Creates an instance of the DecisionService. + * @param {Options} options Configuration options + * @return {DecisionService} An instance of the DecisionService + */ + export function createDecisionService(options: Options): DecisionService; + + interface DecisionService { + + /** + * Gets variation where visitor will be bucketed. + * @param {ProjectConfig} configObj The parsed project configuration object + * @param {string} experimentKey + * @param {string} userId + * @param {UserAttributes} attributes + * @return {string|null} The variation the user is bucketed into. + */ + getVariation( + configObj: ProjectConfig, + experimentKey: string, + userId: string, + attributes?: import('../../shared_types').UserAttributes + ): string | null; + + /** + * Given a feature, user ID, and attributes, returns an object representing a + * decision. If the user was bucketed into a variation for the given feature + * and attributes, the returned decision object will have variation and + * experiment properties (both objects), as well as a decisionSource property. + * decisionSource indicates whether the decision was due to a rollout or an + * experiment. + * @param {ProjectConfig} configObj The parsed project configuration object + * @param {FeatureFlag} feature A feature flag object from project configuration + * @param {string} userId A string identifying the user, for bucketing + * @param {unknown} attributes Optional user attributes + * @return {Decision} An object with experiment, variation, and decisionSource + * properties. If the user was not bucketed into a variation, the variation + * property is null. + */ + getVariationForFeature( + configObj: ProjectConfig, + feature: import('../project_config/entities').FeatureFlag, + userId: string, + attributes: unknown + ): Decision; + + /** + * Removes forced variation for given userId and experimentKey + * @param {unknown} userId String representing the user id + * @param {string} experimentId Number representing the experiment id + * @param {string} experimentKey Key representing the experiment id + * @throws If the user id is not valid or not in the forced variation map + */ + removeForcedVariation(userId: unknown, experimentId: string, experimentKey: string): void; + + /** + * Gets the forced variation key for the given user and experiment. + * @param {ProjectConfig} configObj Object representing project configuration + * @param {string} experimentKey Key for experiment. + * @param {string} userId The user Id. + * @return {string|null} Variation key that specifies the variation which the given user and experiment should be forced into. + */ + getForcedVariation(configObj: ProjectConfig, experimentKey: string, userId: string): string | null; + + /** + * Sets the forced variation for a user in a given experiment + * @param {ProjectConfig} configObj Object representing project configuration + * @param {string} experimentKey Key for experiment. + * @param {string} userId The user Id. + * @param {unknown} variationKey Key for variation. If null, then clear the existing experiment-to-variation mapping + * @return {boolean} A boolean value that indicates if the set completed successfully. + */ + setForcedVariation(configObj: ProjectConfig, experimentKey: string, userId: string, variationKey: unknown): boolean; + } + + interface Options { + userProfileService: import('../../shared_types').UserProfileService | null; + logger: LogHandler; + UNSTABLE_conditionEvaluators: unknown; + } + + interface Decision { + experiment: import('../../shared_types').Experiment | null; + variation: import('../../shared_types').Variation | null; + decisionSource: string; + } +} diff --git a/packages/optimizely-sdk/lib/index.d.ts b/packages/optimizely-sdk/lib/index.d.ts index 3f110095f..c18841e3d 100644 --- a/packages/optimizely-sdk/lib/index.d.ts +++ b/packages/optimizely-sdk/lib/index.d.ts @@ -55,7 +55,7 @@ declare module '@optimizely/optimizely-sdk' { // TODO[OASIS-6649]: Don't use object type // eslint-disable-next-line @typescript-eslint/ban-types jsonSchemaValidator?: object; - userProfileService?: UserProfileService | null; + userProfileService?: import('./shared_types').UserProfileService | null; eventBatchSize?: number; eventFlushInterval?: number; sdkKey?: string; @@ -63,48 +63,73 @@ declare module '@optimizely/optimizely-sdk' { export interface Client { notificationCenter: NotificationCenter; - activate(experimentKey: string, userId: string, attributes?: UserAttributes): string | null; - track(eventKey: string, userId: string, attributes?: UserAttributes, eventTags?: EventTags): void; - getVariation(experimentKey: string, userId: string, attributes?: UserAttributes): string | null; + activate( + experimentKey: string, + userId: string, + attributes?: import('./shared_types').UserAttributes + ): string | null; + track( + eventKey: string, + userId: string, + attributes?: import('./shared_types').UserAttributes, + eventTags?: EventTags + ): void; + getVariation( + experimentKey: string, + userId: string, + attributes?: import('./shared_types').UserAttributes + ): string | null; setForcedVariation(experimentKey: string, userId: string, variationKey: string | null): boolean; getForcedVariation(experimentKey: string, userId: string): string | null; - isFeatureEnabled(featureKey: string, userId: string, attributes?: UserAttributes): boolean; - getEnabledFeatures(userId: string, attributes?: UserAttributes): string[]; - getFeatureVariable(featureKey: string, variableKey: string, userId: string, attributes?: UserAttributes): unknown + isFeatureEnabled( + featureKey: string, + userId: string, + attributes?: import('./shared_types').UserAttributes + ): boolean; + getEnabledFeatures( + userId: string, + attributes?: import('./shared_types').UserAttributes + ): string[]; + getFeatureVariable( + featureKey: string, + variableKey: string, + userId: string, + attributes?: import('./shared_types').UserAttributes + ): unknown; getFeatureVariableBoolean( featureKey: string, variableKey: string, userId: string, - attributes?: UserAttributes + attributes?: import('./shared_types').UserAttributes ): boolean | null; getFeatureVariableDouble( featureKey: string, variableKey: string, userId: string, - attributes?: UserAttributes + attributes?: import('./shared_types').UserAttributes ): number | null; getFeatureVariableInteger( featureKey: string, variableKey: string, userId: string, - attributes?: UserAttributes + attributes?: import('./shared_types').UserAttributes ): number | null; getFeatureVariableString( featureKey: string, variableKey: string, userId: string, - attributes?: UserAttributes + attributes?: import('./shared_types').UserAttributes ): string | null; getFeatureVariableJSON( featureKey: string, variableKey: string, userId: string, - attributes?: UserAttributes + attributes?: import('./shared_types').UserAttributes ): unknown; getAllFeatureVariables( featureKey: string, userId: string, - attributes?: UserAttributes + attributes?: import('./shared_types').UserAttributes ): { [variableKey: string]: unknown }; getOptimizelyConfig(): OptimizelyConfig | null; onReady(options?: { timeout?: number }): Promise<{ success: boolean; reason?: string }>; @@ -135,11 +160,6 @@ declare module '@optimizely/optimizely-sdk' { dispatchEvent: (event: Event, callback: () => void) => void; } - export interface UserProfileService { - lookup: (userId: string) => UserProfile; - save: (profile: UserProfile) => void; - } - // NotificationCenter-related types export interface NotificationCenter { addNotificationListener( @@ -155,21 +175,15 @@ declare module '@optimizely/optimizely-sdk' { export interface ListenerPayload { userId: string; - attributes: UserAttributes; + attributes: import('./shared_types').UserAttributes; } export interface ActivateListenerPayload extends ListenerPayload { - experiment: Experiment; - variation: Variation; + experiment: import('./shared_types').Experiment; + variation: import('./shared_types').Variation; logEvent: Event; } - export type UserAttributes = { - // TODO[OASIS-6649]: Don't use any type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [name: string]: any; - }; - export type EventTags = { [key: string]: string | number | boolean; }; @@ -180,37 +194,6 @@ declare module '@optimizely/optimizely-sdk' { logEvent: Event; } - interface Experiment { - id: string; - key: string; - status: string; - layerId: string; - variations: Variation[]; - trafficAllocation: Array<{ - entityId: string; - endOfRange: number; - }>; - audienceIds: string[]; - // TODO[OASIS-6649]: Don't use object type - // eslint-disable-next-line @typescript-eslint/ban-types - forcedVariations: object; - } - - interface Variation { - id: string; - key: string; - } - - // Information about past bucketing decisions for a user. - export interface UserProfile { - user_id: string; - experiment_bucket_map: { - [experiment_id: string]: { - variation_id: string; - }; - }; - } - /** * Optimizely Config Entities */ diff --git a/packages/optimizely-sdk/lib/shared_types.ts b/packages/optimizely-sdk/lib/shared_types.ts index 90324a9f6..94f86d84a 100644 --- a/packages/optimizely-sdk/lib/shared_types.ts +++ b/packages/optimizely-sdk/lib/shared_types.ts @@ -1,5 +1,41 @@ export type UserAttributes = { - // TODO[OASIS-6649]: Don't use any type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [name: string]: any; + // TODO[OASIS-6649]: Don't use any type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [name: string]: any; +} + +export interface Variation { + id: string; + key: string; +} + +export interface Experiment { + id: string; + key: string; + status: string; + layerId: string; + variations: Variation[]; + trafficAllocation: Array<{ + entityId: string; + endOfRange: number; + }>; + audienceIds: string[]; + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + forcedVariations: object; +} + +// Information about past bucketing decisions for a user. +export interface UserProfile { + user_id: string; + experiment_bucket_map: { + [experiment_id: string]: { + variation_id: string; + }; + }; +} + +export interface UserProfileService { + lookup(userId: string): UserProfile; + save(profile: UserProfile): void; }