diff --git a/packages/optimizely-sdk/CHANGELOG.md b/packages/optimizely-sdk/CHANGELOG.md index 0fc8b8d25..0c7981edc 100644 --- a/packages/optimizely-sdk/CHANGELOG.md +++ b/packages/optimizely-sdk/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Add package.json script for running Karma tests locally using Chrome ([#651](https://github.com/optimizely/javascript-sdk/pull/651)). +- Replaced explicit typescript typings with auto generated ones ([#745](https://github.com/optimizely/javascript-sdk/pull/745)) ## [4.9.1] - January 18, 2022 @@ -18,13 +19,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [4.9.0] - January 14, 2022 ### New Features -* Add a set of new APIs for overriding and managing user-level flag, experiment and delivery rule decisions. These methods can be used for QA and automated testing purposes. They are an extension of the OptimizelyUserContext interface ([#705](https://github.com/optimizely/javascript-sdk/pull/705), [#727](https://github.com/optimizely/javascript-sdk/pull/727), [#729](https://github.com/optimizely/javascript-sdk/pull/729), [#730](https://github.com/optimizely/javascript-sdk/pull/730)): +- Add a set of new APIs for overriding and managing user-level flag, experiment and delivery rule decisions. These methods can be used for QA and automated testing purposes. They are an extension of the OptimizelyUserContext interface ([#705](https://github.com/optimizely/javascript-sdk/pull/705), [#727](https://github.com/optimizely/javascript-sdk/pull/727), [#729](https://github.com/optimizely/javascript-sdk/pull/729), [#730](https://github.com/optimizely/javascript-sdk/pull/730)): - setForcedDecision - getForcedDecision - removeForcedDecision - removeAllForcedDecisions -* For details, refer to our documentation pages: [OptimizelyUserContext](https://docs.developers.optimizely.com/full-stack/v4.0/docs/optimizelyusercontext-javascript-node) and [Forced Decision methods](https://docs.developers.optimizely.com/full-stack/v4.0/docs/forced-decision-methods-javascript-node). +- For details, refer to our documentation pages: [OptimizelyUserContext](https://docs.developers.optimizely.com/full-stack/v4.0/docs/optimizelyusercontext-javascript-node) and [Forced Decision methods](https://docs.developers.optimizely.com/full-stack/v4.0/docs/forced-decision-methods-javascript-node). ## [4.8.0] - November 29, 2021 diff --git a/packages/optimizely-sdk/lib/core/project_config/index.ts b/packages/optimizely-sdk/lib/core/project_config/index.ts index 2ea2b8b41..625838811 100644 --- a/packages/optimizely-sdk/lib/core/project_config/index.ts +++ b/packages/optimizely-sdk/lib/core/project_config/index.ts @@ -1,5 +1,5 @@ /** - * Copyright 2016-2021, Optimizely + * Copyright 2016-2022, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,9 @@ import { } from '../../shared_types'; interface TryCreatingProjectConfigConfig { - datafile: string; + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + datafile: string | object; jsonSchemaValidator?: { validate(jsonObject: unknown): boolean, }; diff --git a/packages/optimizely-sdk/lib/core/project_config/project_config_manager.ts b/packages/optimizely-sdk/lib/core/project_config/project_config_manager.ts index 174a92c32..861052670 100644 --- a/packages/optimizely-sdk/lib/core/project_config/project_config_manager.ts +++ b/packages/optimizely-sdk/lib/core/project_config/project_config_manager.ts @@ -1,5 +1,5 @@ /** - * Copyright 2019-2021, Optimizely + * Copyright 2019-2022, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,9 @@ const logger = getLogger(); const MODULE_NAME = 'PROJECT_CONFIG_MANAGER'; interface ProjectConfigManagerConfig { - datafile?: string, + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + datafile?: string | object, jsonSchemaValidator?: { validate(jsonObject: unknown): boolean, }; @@ -169,10 +171,12 @@ export class ProjectConfigManager { * the new config object's revision is newer than the current one, sets/updates the project config * and optimizely config object instance variables and returns null for the error. If unsuccessful, * the project config and optimizely config objects will not be updated, and the error is returned. - * @param {string} newDatafile + * @param {string | object} newDatafile * @returns {Error|null} error or null */ - private handleNewDatafile(newDatafile: string): Error | null { + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + private handleNewDatafile(newDatafile: string | object): Error | null { const { configObj, error } = tryCreatingProjectConfig({ datafile: newDatafile, jsonSchemaValidator: this.jsonSchemaValidator, diff --git a/packages/optimizely-sdk/lib/export_types.ts b/packages/optimizely-sdk/lib/export_types.ts new file mode 100644 index 000000000..17d307ae8 --- /dev/null +++ b/packages/optimizely-sdk/lib/export_types.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2022, 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. + */ +export { + UserAttributes, + OptimizelyConfig, + OptimizelyVariable, + OptimizelyVariation, + OptimizelyExperiment, + OptimizelyFeature, + OptimizelyDecisionContext, + OptimizelyForcedDecision, + EventTags, + Event, + EventDispatcher, + DatafileOptions, + OptimizelyOptions, + UserProfileService, + UserProfile, + ListenerPayload, + OptimizelyDecision, + OptimizelyUserContext, + NotificationListener, + Config, + Client, + ActivateListenerPayload, + TrackListenerPayload, + NotificationCenter +} from './shared_types' diff --git a/packages/optimizely-sdk/lib/index.browser.ts b/packages/optimizely-sdk/lib/index.browser.ts index 59d23e694..7411fc22a 100644 --- a/packages/optimizely-sdk/lib/index.browser.ts +++ b/packages/optimizely-sdk/lib/index.browser.ts @@ -1,5 +1,5 @@ /** - * Copyright 2016-2017, 2019-2020 Optimizely + * Copyright 2016-2017, 2019-2022 Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ import Optimizely from './optimizely'; import eventProcessorConfigValidator from './utils/event_processor_config_validator'; import { createNotificationCenter } from './core/notification_center'; import { default as eventProcessor } from './plugins/event_processor'; -import { SDKOptions, OptimizelyDecideOption } from './shared_types'; +import { OptimizelyDecideOption, Client, Config } from './shared_types'; import { createHttpPollingDatafileManager } from './plugins/datafile_manager/http_polling_datafile_manager'; const logger = getLogger(); @@ -47,13 +47,15 @@ let hasRetriedEvents = false; /** * Creates an instance of the Optimizely class - * @param {SDKOptions} config - * @return {Optimizely|null} the Optimizely object + * @param {Config} config + * @return {Client|null} the Optimizely client object * null on error */ -const createInstance = function(config: SDKOptions): Optimizely | null { +const createInstance = function(config: Config): Client | null { try { // TODO warn about setting per instance errorHandler / logger / logLevel + let isValidInstance = false + if (config.errorHandler) { setErrorHandler(config.errorHandler); } @@ -68,10 +70,9 @@ const createInstance = function(config: SDKOptions): Optimizely | null { try { configValidator.validate(config); - config.isValidInstance = true; + isValidInstance = true; } catch (ex) { logger.error(ex); - config.isValidInstance = false; } let eventDispatcher; @@ -125,6 +126,7 @@ const createInstance = function(config: SDKOptions): Optimizely | null { errorHandler, datafileManager: config.sdkKey ? createHttpPollingDatafileManager(config.sdkKey, logger, config.datafile, config.datafileOptions) : undefined, notificationCenter, + isValidInstance: isValidInstance }; const optimizely = new Optimizely(optimizelyOptions); @@ -181,3 +183,5 @@ export default { __internalResetRetryState, OptimizelyDecideOption, }; + +export * from './export_types' diff --git a/packages/optimizely-sdk/lib/index.d.ts b/packages/optimizely-sdk/lib/index.d.ts deleted file mode 100644 index 089d94ca3..000000000 --- a/packages/optimizely-sdk/lib/index.d.ts +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright 2018-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' { - import { LogHandler, ErrorHandler } from '@optimizely/js-sdk-logging'; - import * as enums from '@optimizely/optimizely-sdk/lib/utils/enums'; - import * as logging from '@optimizely/optimizely-sdk/lib/plugins/logger'; - - export { enums, logging }; - - export function setLogger(logger: LogHandler | null): void; - - export function setLogLevel(level: enums.LOG_LEVEL | string): void; - - export function createInstance(config: Config): Client; - - export const errorHandler: ErrorHandler; - - export const eventDispatcher: EventDispatcher; - - export type UserAttributes = import('./shared_types').UserAttributes; - - export type OptimizelyConfig = import('./shared_types').OptimizelyConfig; - - export type OptimizelyVariable = import('./shared_types').OptimizelyVariable; - - export type OptimizelyVariation = import('./shared_types').OptimizelyVariation; - - export type OptimizelyExperiment = import('./shared_types').OptimizelyExperiment; - - export type OptimizelyFeature = import('./shared_types').OptimizelyFeature; - - export type OptimizelyDecisionContext = import('./shared_types').OptimizelyDecisionContext; - - export type OptimizelyForcedDecision = import('./shared_types').OptimizelyForcedDecision; - - export type EventTags = import('./shared_types').EventTags; - - export type Event = import('./shared_types').Event; - - export type EventDispatcher = import('./shared_types').EventDispatcher; - - export type DatafileOptions = import('./shared_types').DatafileOptions; - - export type SDKOptions = import('./shared_types').SDKOptions; - - export type OptimizelyOptions = import('./shared_types').OptimizelyOptions; - - export type UserProfileService = import('./shared_types').UserProfileService; - - export type UserProfile = import('./shared_types').UserProfile; - - export type ListenerPayload = import('./shared_types').ListenerPayload; - - export type OptimizelyDecision = import('./shared_types').OptimizelyDecision; - - export type OptimizelyUserContext = import('./shared_types').OptimizelyUserContext; - - export enum OptimizelyDecideOption { - DISABLE_DECISION_EVENT = 'DISABLE_DECISION_EVENT', - ENABLED_FLAGS_ONLY = 'ENABLED_FLAGS_ONLY', - IGNORE_USER_PROFILE_SERVICE = 'IGNORE_USER_PROFILE_SERVICE', - INCLUDE_REASONS = 'INCLUDE_REASONS', - EXCLUDE_VARIABLES = 'EXCLUDE_VARIABLES' - } - - export type NotificationListener = import('./shared_types').NotificationListener; - - // The options object given to Optimizely.createInstance. - export interface Config { - // TODO[OASIS-6649]: Don't use object type - // eslint-disable-next-line @typescript-eslint/ban-types - datafile?: object | string; - datafileOptions?: DatafileOptions; - errorHandler?: ErrorHandler; - eventDispatcher?: EventDispatcher; - logger?: LogHandler; - logLevel?: - | string - | enums.LOG_LEVEL.DEBUG - | enums.LOG_LEVEL.ERROR - | enums.LOG_LEVEL.INFO - | enums.LOG_LEVEL.NOTSET - | enums.LOG_LEVEL.WARNING; - jsonSchemaValidator?: { - validate(jsonObject: unknown): boolean, - }; - userProfileService?: UserProfileService | null; - eventBatchSize?: number; - eventFlushInterval?: number; - sdkKey?: string; - defaultDecideOptions?: OptimizelyDecideOption[] - } - - export interface Client { - notificationCenter: NotificationCenter; - createUserContext( - userId: string, - attributes?: UserAttributes - ): OptimizelyUserContext | null; - 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; - 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; - getFeatureVariableBoolean( - featureKey: string, - variableKey: string, - userId: string, - attributes?: UserAttributes - ): boolean | null; - getFeatureVariableDouble( - featureKey: string, - variableKey: string, - userId: string, - attributes?: UserAttributes - ): number | null; - getFeatureVariableInteger( - featureKey: string, - variableKey: string, - userId: string, - attributes?: UserAttributes - ): number | null; - getFeatureVariableString( - featureKey: string, - variableKey: string, - userId: string, - attributes?: UserAttributes - ): string | null; - getFeatureVariableJSON( - featureKey: string, - variableKey: string, - userId: string, - attributes?: UserAttributes - ): unknown; - getAllFeatureVariables( - featureKey: string, - userId: string, - attributes?: UserAttributes - ): { [variableKey: string]: unknown } | null; - getOptimizelyConfig(): OptimizelyConfig | null; - onReady(options?: { timeout?: number }): Promise<{ success: boolean; reason?: string }>; - close(): Promise<{ success: boolean; reason?: string }>; - } - - // NotificationCenter-related types - export interface NotificationCenter { - addNotificationListener( - notificationType: string, - callback: NotificationListener - ): number; - removeNotificationListener(listenerId: number): boolean; - clearAllNotificationListeners(): void; - clearNotificationListeners(notificationType: enums.NOTIFICATION_TYPES): void; - } - - export interface ActivateListenerPayload extends ListenerPayload { - experiment: import('./shared_types').Experiment; - variation: import('./shared_types').Variation; - logEvent: Event; - } - - export interface TrackListenerPayload extends ListenerPayload { - eventKey: string; - eventTags: EventTags; - logEvent: Event; - } -} - -declare module '@optimizely/optimizely-sdk/lib/utils/enums' { - import { LogLevel } from '@optimizely/js-sdk-logging'; - - export { LogLevel as LOG_LEVEL }; - - export enum NOTIFICATION_TYPES { - ACTIVATE = 'ACTIVATE:experiment, user_id,attributes, variation, event', - DECISION = 'DECISION:type, userId, attributes, decisionInfo', - OPTIMIZELY_CONFIG_UPDATE = 'OPTIMIZELY_CONFIG_UPDATE', - TRACK = 'TRACK:event_key, user_id, attributes, event_tags, event', - LOG_EVENT = "LOG_EVENT:logEvent" - } -} - -declare module '@optimizely/optimizely-sdk/lib/plugins/logger' { - import * as enums from '@optimizely/optimizely-sdk/lib/utils/enums'; - import { LogHandler } from '@optimizely/js-sdk-logging'; - - export interface LoggerConfig { - logLevel?: enums.LOG_LEVEL | string; - logToConsole?: boolean; - prefix?: string; - } - export function createLogger(config?: LoggerConfig): LogHandler; - export function createNoOpLogger(): LogHandler; -} - -declare module '@optimizely/optimizely-sdk/lib/plugins/event_dispatcher' {} - -declare module '@optimizely/optimizely-sdk/lib/utils/json_schema_validator' {} - -declare module '@optimizely/optimizely-sdk/lib/plugins/error_handler' {} diff --git a/packages/optimizely-sdk/lib/index.lite.ts b/packages/optimizely-sdk/lib/index.lite.ts index 86e30876d..3e46b8878 100644 --- a/packages/optimizely-sdk/lib/index.lite.ts +++ b/packages/optimizely-sdk/lib/index.lite.ts @@ -1,5 +1,5 @@ /** - * Copyright 2021, Optimizely + * Copyright 2021-2022, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import * as loggerPlugin from './plugins/logger'; import Optimizely from './optimizely'; import { createNotificationCenter } from './core/notification_center'; import { createForwardingEventProcessor } from './plugins/event_processor/forwarding_event_processor'; -import { SDKOptions, OptimizelyDecideOption } from './shared_types'; +import { OptimizelyDecideOption, Client, ConfigLite } from './shared_types'; import { createNoOpDatafileManager } from './plugins/datafile_manager/no_op_datafile_manager'; const logger = getLogger(); @@ -38,14 +38,16 @@ setLogLevel(LogLevel.ERROR); /** * Creates an instance of the Optimizely class - * @param {SDKOptions} config - * @return {Optimizely|null} the Optimizely object + * @param {ConfigLite} config + * @return {Client|null} the Optimizely client object * null on error */ -const createInstance = function(config: SDKOptions): Optimizely | null { + const createInstance = function(config: ConfigLite): Client | null { try { // TODO warn about setting per instance errorHandler / logger / logLevel + let isValidInstance = false; + if (config.errorHandler) { setErrorHandler(config.errorHandler); } @@ -60,10 +62,9 @@ const createInstance = function(config: SDKOptions): Optimizely | null { try { configValidator.validate(config); - config.isValidInstance = true; + isValidInstance = true; } catch (ex) { logger.error(ex); - config.isValidInstance = false; } const errorHandler = getErrorHandler(); @@ -79,6 +80,7 @@ const createInstance = function(config: SDKOptions): Optimizely | null { datafileManager: createNoOpDatafileManager(), eventProcessor, notificationCenter, + isValidInstance: isValidInstance, }; const optimizely = new Optimizely(optimizelyOptions); @@ -110,3 +112,5 @@ export default { createInstance, OptimizelyDecideOption, }; + +export * from './export_types' diff --git a/packages/optimizely-sdk/lib/index.node.ts b/packages/optimizely-sdk/lib/index.node.ts index 99b5c7cd6..6c1a71f20 100644 --- a/packages/optimizely-sdk/lib/index.node.ts +++ b/packages/optimizely-sdk/lib/index.node.ts @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright 2016-2017, 2019-2021 Optimizely, Inc. and contributors * + * Copyright 2016-2017, 2019-2022 Optimizely, Inc. and contributors * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * @@ -30,7 +30,7 @@ import defaultEventDispatcher from './plugins/event_dispatcher/index.node'; import eventProcessorConfigValidator from './utils/event_processor_config_validator'; import { createNotificationCenter } from './core/notification_center'; import { createEventProcessor } from './plugins/event_processor'; -import { SDKOptions, OptimizelyDecideOption } from './shared_types'; +import { OptimizelyDecideOption, Client, Config } from './shared_types'; import { createHttpPollingDatafileManager } from './plugins/datafile_manager/http_polling_datafile_manager'; const logger = getLogger(); @@ -42,13 +42,14 @@ const DEFAULT_EVENT_MAX_QUEUE_SIZE = 10000; /** * Creates an instance of the Optimizely class - * @param {SDKOptions} config - * @return {Optimizely|null} the Optimizely object + * @param {Config} config + * @return {Client|null} the Optimizely client object * null on error */ -const createInstance = function(config: SDKOptions): Optimizely | null { + const createInstance = function(config: Config): Client | null { try { let hasLogger = false; + let isValidInstance = false; // TODO warn about setting per instance errorHandler / logger / logLevel if (config.errorHandler) { @@ -66,14 +67,13 @@ const createInstance = function(config: SDKOptions): Optimizely | null { } try { configValidator.validate(config); - config.isValidInstance = true; + isValidInstance = true; } catch (ex) { if (hasLogger) { logger.error(ex); } else { console.error(ex.message); } - config.isValidInstance = false; } let eventBatchSize = config.eventBatchSize; @@ -113,6 +113,7 @@ const createInstance = function(config: SDKOptions): Optimizely | null { errorHandler, datafileManager: config.sdkKey ? createHttpPollingDatafileManager(config.sdkKey, logger, config.datafile, config.datafileOptions) : undefined, notificationCenter, + isValidInstance: isValidInstance, }; return new Optimizely(optimizelyOptions); @@ -146,3 +147,5 @@ export default { createInstance, OptimizelyDecideOption, }; + +export * from './export_types' diff --git a/packages/optimizely-sdk/lib/index.react_native.ts b/packages/optimizely-sdk/lib/index.react_native.ts index 75c38cdcd..67f7f46be 100644 --- a/packages/optimizely-sdk/lib/index.react_native.ts +++ b/packages/optimizely-sdk/lib/index.react_native.ts @@ -1,5 +1,5 @@ /** - * Copyright 2019-2021 Optimizely + * Copyright 2019-2022 Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import defaultEventDispatcher from './plugins/event_dispatcher/index.browser'; import eventProcessorConfigValidator from './utils/event_processor_config_validator'; import { createNotificationCenter } from './core/notification_center'; import { createEventProcessor } from './plugins/event_processor'; -import { SDKOptions, OptimizelyDecideOption } from './shared_types'; +import { OptimizelyDecideOption, Client, Config } from './shared_types'; import { createHttpPollingDatafileManager } from './plugins/datafile_manager/http_polling_datafile_manager'; const logger = getLogger(); @@ -43,13 +43,15 @@ const DEFAULT_EVENT_MAX_QUEUE_SIZE = 10000; /** * Creates an instance of the Optimizely class - * @param {SDKOptions} config - * @return {Optimizely|null} the Optimizely object + * @param {Config} config + * @return {Client|null} the Optimizely client object * null on error */ -const createInstance = function(config: SDKOptions): Optimizely | null { + const createInstance = function(config: Config): Client | null { try { // TODO warn about setting per instance errorHandler / logger / logLevel + let isValidInstance = false; + if (config.errorHandler) { setErrorHandler(config.errorHandler); } @@ -64,10 +66,9 @@ const createInstance = function(config: SDKOptions): Optimizely | null { try { configValidator.validate(config); - config.isValidInstance = true; + isValidInstance = true; } catch (ex) { logger.error(ex); - config.isValidInstance = false; } let eventBatchSize = config.eventBatchSize; @@ -107,6 +108,7 @@ const createInstance = function(config: SDKOptions): Optimizely | null { errorHandler, datafileManager: config.sdkKey ? createHttpPollingDatafileManager(config.sdkKey, logger, config.datafile, config.datafileOptions) : undefined, notificationCenter, + isValidInstance: isValidInstance, }; // If client engine is react, convert it to react native. @@ -145,3 +147,5 @@ export default { createInstance, OptimizelyDecideOption, }; + +export * from './export_types' diff --git a/packages/optimizely-sdk/lib/optimizely/index.ts b/packages/optimizely-sdk/lib/optimizely/index.ts index 58bc0e712..f677e418d 100644 --- a/packages/optimizely-sdk/lib/optimizely/index.ts +++ b/packages/optimizely-sdk/lib/optimizely/index.ts @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************/ -import { find, sprintf, objectValues, NotificationCenter } from '@optimizely/js-sdk-utils'; +import { sprintf, objectValues } from '@optimizely/js-sdk-utils'; import { LoggerFacade, ErrorHandler } from '@optimizely/js-sdk-logging'; import { EventProcessor } from '@optimizely/js-sdk-event-processor'; +import {NotificationCenter} from '../core/notification_center' import { UserAttributes, @@ -26,7 +27,6 @@ import { Variation, FeatureFlag, FeatureVariable, - OptimizelyVariation, OptimizelyOptions, OptimizelyDecideOption, OptimizelyDecision @@ -78,10 +78,10 @@ export default class Optimizely { private errorHandler: ErrorHandler; private logger: LoggerFacade; private projectConfigManager: ProjectConfigManager; - private notificationCenter: NotificationCenter; private decisionService: DecisionService; private eventProcessor: EventProcessor; private defaultDecideOptions: { [key: string]: boolean }; + public notificationCenter: NotificationCenter; constructor(config: OptimizelyOptions) { let clientEngine = config.clientEngine; diff --git a/packages/optimizely-sdk/lib/optimizely_user_context/index.ts b/packages/optimizely-sdk/lib/optimizely_user_context/index.ts index 2fcf78238..7ab5f0a22 100644 --- a/packages/optimizely-sdk/lib/optimizely_user_context/index.ts +++ b/packages/optimizely-sdk/lib/optimizely_user_context/index.ts @@ -15,20 +15,14 @@ ***************************************************************************/ import Optimizely from '../../lib/optimizely'; import { - DecisionResponse, EventTags, OptimizelyDecideOption, OptimizelyDecision, OptimizelyDecisionContext, OptimizelyForcedDecision, UserAttributes, - Variation } from '../../lib/shared_types'; -import { - getFlagVariationByKey, - ProjectConfig, -} from '../core/project_config'; -import { LOG_MESSAGES, CONTROL_ATTRIBUTES } from '../utils/enums'; +import { CONTROL_ATTRIBUTES } from '../utils/enums'; export default class OptimizelyUserContext { private optimizely: Optimizely; diff --git a/packages/optimizely-sdk/lib/plugins/datafile_manager/http_polling_datafile_manager.ts b/packages/optimizely-sdk/lib/plugins/datafile_manager/http_polling_datafile_manager.ts index 5cca10bed..42f993145 100644 --- a/packages/optimizely-sdk/lib/plugins/datafile_manager/http_polling_datafile_manager.ts +++ b/packages/optimizely-sdk/lib/plugins/datafile_manager/http_polling_datafile_manager.ts @@ -1,5 +1,5 @@ /** - * Copyright 2021, Optimizely + * Copyright 2021-2022, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,10 @@ import fns from '../../utils/fns'; export function createHttpPollingDatafileManager( sdkKey: string, - logger: LoggerFacade, - datafile?: string, + logger: LoggerFacade, + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + datafile?: string | object, datafileOptions?: DatafileOptions, ): DatafileManager { const datafileManagerConfig: DatafileManagerConfig = { sdkKey }; diff --git a/packages/optimizely-sdk/lib/plugins/event_dispatcher/index.browser.ts b/packages/optimizely-sdk/lib/plugins/event_dispatcher/index.browser.ts index 2c4a979cd..9f0da6d0a 100644 --- a/packages/optimizely-sdk/lib/plugins/event_dispatcher/index.browser.ts +++ b/packages/optimizely-sdk/lib/plugins/event_dispatcher/index.browser.ts @@ -1,5 +1,5 @@ /** - * Copyright 2016-2017, 2020-2021, Optimizely + * Copyright 2016-2017, 2020-2022, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ const POST_METHOD = 'POST'; const GET_METHOD = 'GET'; const READYSTATE_COMPLETE = 4; -interface Event { +export interface Event { url: string; httpVerb: 'POST' | 'GET'; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/optimizely-sdk/lib/shared_types.ts b/packages/optimizely-sdk/lib/shared_types.ts index 93f955d14..de4c23bbe 100644 --- a/packages/optimizely-sdk/lib/shared_types.ts +++ b/packages/optimizely-sdk/lib/shared_types.ts @@ -16,7 +16,8 @@ import { ErrorHandler, LogHandler, LogLevel, LoggerFacade } from '@optimizely/js-sdk-logging'; import { EventProcessor } from '@optimizely/js-sdk-event-processor'; -import { NotificationCenter } from '@optimizely/js-sdk-utils'; +import { NOTIFICATION_TYPES } from '@optimizely/js-sdk-utils'; +import {NotificationCenter as NotificationCenterImpl} from './core/notification_center' export interface BucketerParams { experimentId: string; @@ -81,6 +82,17 @@ export interface ListenerPayload { export type NotificationListener = (notificationData: T) => void; +// NotificationCenter-related types +export interface NotificationCenter { + addNotificationListener( + notificationType: string, + callback: NotificationListener + ): number; + removeNotificationListener(listenerId: number): boolean; + clearAllNotificationListeners(): void; + clearNotificationListeners(notificationType: NOTIFICATION_TYPES): void; +} + // An event to be submitted to Optimizely, enabling tracking the reach and impact of // tests and feature rollouts. export interface Event { @@ -229,7 +241,9 @@ export interface OptimizelyOptions { UNSTABLE_conditionEvaluators?: unknown; clientEngine: string; clientVersion?: string; - datafile?: string; + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + datafile?: string | object; datafileManager?: DatafileManager; errorHandler: ErrorHandler; eventProcessor: EventProcessor; @@ -241,7 +255,7 @@ export interface OptimizelyOptions { sdkKey?: string; userProfileService?: UserProfileService | null; defaultDecideOptions?: OptimizelyDecideOption[]; - notificationCenter: NotificationCenter; + notificationCenter: NotificationCenterImpl; } /** @@ -263,36 +277,141 @@ export interface OptimizelyVariable { value: string; } +export interface Client { + notificationCenter: NotificationCenter; + createUserContext( + userId: string, + attributes?: UserAttributes + ): OptimizelyUserContext | null; + 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; + 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; + getFeatureVariableBoolean( + featureKey: string, + variableKey: string, + userId: string, + attributes?: UserAttributes + ): boolean | null; + getFeatureVariableDouble( + featureKey: string, + variableKey: string, + userId: string, + attributes?: UserAttributes + ): number | null; + getFeatureVariableInteger( + featureKey: string, + variableKey: string, + userId: string, + attributes?: UserAttributes + ): number | null; + getFeatureVariableString( + featureKey: string, + variableKey: string, + userId: string, + attributes?: UserAttributes + ): string | null; + getFeatureVariableJSON( + featureKey: string, + variableKey: string, + userId: string, + attributes?: UserAttributes + ): unknown; + getAllFeatureVariables( + featureKey: string, + userId: string, + attributes?: UserAttributes + ): { [variableKey: string]: unknown } | null; + getOptimizelyConfig(): OptimizelyConfig | null; + onReady(options?: { timeout?: number }): Promise<{ success: boolean; reason?: string }>; + close(): Promise<{ success: boolean; reason?: string }>; +} + +export interface ActivateListenerPayload extends ListenerPayload { + experiment: import('./shared_types').Experiment; + variation: import('./shared_types').Variation; + logEvent: Event; +} + +export interface TrackListenerPayload extends ListenerPayload { + eventKey: string; + eventTags: EventTags; + logEvent: Event; +} + /** * Entry level Config Entities + * For compatibility with the previous declaration file */ -export interface SDKOptions { - // Datafile string - datafile?: string; + export interface Config extends ConfigLite { // options for Datafile Manager datafileOptions?: DatafileOptions; - // errorHandler object for logging error - errorHandler?: ErrorHandler; // limit of events to dispatch in a batch eventBatchSize?: number; - // event dispatcher function - eventDispatcher?: EventDispatcher; // maximum time for an event to stay in the queue eventFlushInterval?: number; // maximum size for the event queue eventMaxQueueSize?: number; - // flag to validate if this instance is valid - isValidInstance: boolean; + // sdk key + sdkKey?: string; +} + +/** + * Entry level Config Entities for Lite bundle + * For compatibility with the previous declaration file + */ + export interface ConfigLite { + // Datafile string + // TODO[OASIS-6649]: Don't use object type + // eslint-disable-next-line @typescript-eslint/ban-types + datafile?: object | string; + // errorHandler object for logging error + errorHandler?: ErrorHandler; + // event dispatcher function + eventDispatcher?: EventDispatcher; + // The object to validate against the schema + jsonSchemaValidator?: { + validate(jsonObject: unknown): boolean, + }; // level of logging i.e debug, info, error, warning etc logLevel?: LogLevel | string; // LogHandler object for logging logger?: LogHandler; - // sdk key - sdkKey?: string; // user profile that contains user information userProfileService?: UserProfileService; // dafault options for decide API defaultDecideOptions?: OptimizelyDecideOption[]; + clientEngine?: string; + clientVersion?: string; } export type OptimizelyExperimentsMap = { @@ -370,14 +489,14 @@ export interface OptimizelyUserContext { setAttribute(key: string, value: unknown): void; decide( key: string, - options: OptimizelyDecideOption[] + options?: OptimizelyDecideOption[] ): OptimizelyDecision; decideForKeys( keys: string[], - options: OptimizelyDecideOption[], + options?: OptimizelyDecideOption[], ): { [key: string]: OptimizelyDecision }; decideAll( - options: OptimizelyDecideOption[], + options?: OptimizelyDecideOption[], ): { [key: string]: OptimizelyDecision }; trackEvent(eventName: string, eventTags?: EventTags): void; setForcedDecision(context: OptimizelyDecisionContext, decision: OptimizelyForcedDecision): boolean; diff --git a/packages/optimizely-sdk/package.json b/packages/optimizely-sdk/package.json index 5e86c1d29..6d0f7e9e1 100644 --- a/packages/optimizely-sdk/package.json +++ b/packages/optimizely-sdk/package.json @@ -6,7 +6,7 @@ "main": "dist/optimizely.node.min.js", "browser": "dist/optimizely.browser.min.js", "react-native": "dist/optimizely.react_native.min.js", - "typings": "lib/index.d.ts", + "typings": "dist/index.node.d.ts", "scripts": { "clean": "rm -rf dist", "lint": "tsc --noEmit && eslint 'lib/**/*.js' 'lib/**/*.ts'", @@ -17,7 +17,7 @@ "test-umdbrowser": "npm run build-browser-umd && karma start karma.umd.conf.js --single-run", "test-karma-local": "karma start karma.local_chrome.bs.conf.js && npm run build-browser-umd && karma start karma.local_chrome.umd.conf.js", "prebuild": "npm run clean", - "build": "rollup -c", + "build": "rollup -c && cp dist/index.lite.d.ts dist/optimizely.lite.es.d.ts && cp dist/index.lite.d.ts dist/optimizely.lite.es.min.d.ts && cp dist/index.lite.d.ts dist/optimizely.lite.min.d.ts", "build-browser-umd": "rollup -c --config-umd", "precover": "nyc npm test", "cover": "nyc report -r lcov", diff --git a/packages/optimizely-sdk/tsconfig.json b/packages/optimizely-sdk/tsconfig.json index d7ec24942..1ce245676 100644 --- a/packages/optimizely-sdk/tsconfig.json +++ b/packages/optimizely-sdk/tsconfig.json @@ -8,7 +8,7 @@ ] }, "allowJs": true, - "declaration": false, + "declaration": true, "module": "esnext", "outDir": "./dist", "sourceMap": true