From db17fe927369b0abea2d35b511d0eeda321b6f5a Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Tue, 25 Feb 2025 01:19:46 +0600 Subject: [PATCH 1/2] [FSSDK-10992] add universal entrypoint --- lib/entrypoint.universal.test-d.ts | 95 +++++++++++++++ .../event_dispatcher_factory.ts | 7 ++ .../event_processor_factory.universal.ts | 56 +++++++++ lib/export_types.ts | 2 - lib/index.lite.ts | 1 - lib/index.universal.ts | 115 ++++++++++++++++++ .../config_manager_factory.universal.ts | 32 +++++ package.json | 2 +- rollup.config.js | 4 +- 9 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 lib/entrypoint.universal.test-d.ts create mode 100644 lib/event_processor/event_dispatcher/event_dispatcher_factory.ts create mode 100644 lib/event_processor/event_processor_factory.universal.ts delete mode 100644 lib/index.lite.ts create mode 100644 lib/index.universal.ts create mode 100644 lib/project_config/config_manager_factory.universal.ts diff --git a/lib/entrypoint.universal.test-d.ts b/lib/entrypoint.universal.test-d.ts new file mode 100644 index 000000000..1b5afb060 --- /dev/null +++ b/lib/entrypoint.universal.test-d.ts @@ -0,0 +1,95 @@ +/** + * Copyright 2025, 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 + * + * https://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. + */ + +import { expectTypeOf } from 'vitest'; + +import * as universal from './index.universal'; + +type WithoutReadonly = { -readonly [P in keyof T]: T[P] }; + +const universalEntrypoint: WithoutReadonly = universal; + +import { + Config, + Client, + StaticConfigManagerConfig, + OpaqueConfigManager, + EventDispatcher, + OpaqueEventProcessor, + OpaqueLevelPreset, + LoggerConfig, + OpaqueLogger, + ErrorHandler, + OpaqueErrorNotifier, +} from './export_types'; + +import { UniversalPollingConfigManagerConfig } from './project_config/config_manager_factory.universal'; +import { RequestHandler } from './utils/http_request_handler/http'; +import { UniversalBatchEventProcessorOptions } from './event_processor/event_processor_factory.universal'; +import { + DECISION_SOURCES, + DECISION_NOTIFICATION_TYPES, + NOTIFICATION_TYPES, +} from './utils/enums'; + +import { LogLevel } from './logging/logger'; + +import { OptimizelyDecideOption } from './shared_types'; + +export type UniversalEntrypoint = { + // client factory + createInstance: (config: Config) => Client | null; + + // config manager related exports + createStaticProjectConfigManager: (config: StaticConfigManagerConfig) => OpaqueConfigManager; + createPollingProjectConfigManager: (config: UniversalPollingConfigManagerConfig) => OpaqueConfigManager; + + // event processor related exports + createEventDispatcher: (requestHandler: RequestHandler) => EventDispatcher; + createForwardingEventProcessor: (eventDispatcher: EventDispatcher) => OpaqueEventProcessor; + createBatchEventProcessor: (options: UniversalBatchEventProcessorOptions) => OpaqueEventProcessor; + + // TODO: odp manager related exports + // createOdpManager: (options: OdpManagerOptions) => OpaqueOdpManager; + + // TODO: vuid manager related exports + // createVuidManager: (options: VuidManagerOptions) => OpaqueVuidManager; + + // logger related exports + LogLevel: typeof LogLevel; + DebugLog: OpaqueLevelPreset, + InfoLog: OpaqueLevelPreset, + WarnLog: OpaqueLevelPreset, + ErrorLog: OpaqueLevelPreset, + createLogger: (config: LoggerConfig) => OpaqueLogger; + + // error related exports + createErrorNotifier: (errorHandler: ErrorHandler) => OpaqueErrorNotifier; + + // enums + DECISION_SOURCES: typeof DECISION_SOURCES; + DECISION_NOTIFICATION_TYPES: typeof DECISION_NOTIFICATION_TYPES; + NOTIFICATION_TYPES: typeof NOTIFICATION_TYPES; + + // decide options + OptimizelyDecideOption: typeof OptimizelyDecideOption; + + // client engine + clientEngine: string; +} + + +expectTypeOf(universalEntrypoint).toEqualTypeOf(); diff --git a/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts b/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts new file mode 100644 index 000000000..9df8515c5 --- /dev/null +++ b/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts @@ -0,0 +1,7 @@ +import { RequestHandler } from '../../utils/http_request_handler/http'; +import { DefaultEventDispatcher } from './default_dispatcher'; +import { EventDispatcher } from './event_dispatcher'; + +export const createEventDispatcher = (requestHander: RequestHandler): EventDispatcher => { + return new DefaultEventDispatcher(requestHander); +} diff --git a/lib/event_processor/event_processor_factory.universal.ts b/lib/event_processor/event_processor_factory.universal.ts new file mode 100644 index 000000000..40ef4a93d --- /dev/null +++ b/lib/event_processor/event_processor_factory.universal.ts @@ -0,0 +1,56 @@ +/** + * Copyright 2025, 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. + */ + +import { getForwardingEventProcessor } from './forwarding_event_processor'; +import { EventDispatcher } from './event_dispatcher/event_dispatcher'; + +import { + getOpaqueBatchEventProcessor, + BatchEventProcessorOptions, + OpaqueEventProcessor, + wrapEventProcessor, + getPrefixEventStore, +} from './event_processor_factory'; + +import { FAILED_EVENT_RETRY_INTERVAL } from './event_processor_factory'; + +export const createForwardingEventProcessor = ( + eventDispatcher: EventDispatcher +): OpaqueEventProcessor => { + return wrapEventProcessor(getForwardingEventProcessor(eventDispatcher)); +}; + +export type UniversalBatchEventProcessorOptions = Omit & { + eventDispatcher: EventDispatcher; +} + +export const createBatchEventProcessor = ( + options: UniversalBatchEventProcessorOptions +): OpaqueEventProcessor => { + const eventStore = options.eventStore ? getPrefixEventStore(options.eventStore) : undefined; + + return getOpaqueBatchEventProcessor({ + eventDispatcher: options.eventDispatcher, + closingEventDispatcher: options.closingEventDispatcher, + flushInterval: options.flushInterval, + batchSize: options.batchSize, + retryOptions: { + maxRetries: 5, + }, + failedEventRetryInterval: FAILED_EVENT_RETRY_INTERVAL, + eventStore: eventStore, + }); +}; diff --git a/lib/export_types.ts b/lib/export_types.ts index be8b77254..fba5cde09 100644 --- a/lib/export_types.ts +++ b/lib/export_types.ts @@ -67,8 +67,6 @@ export type { NotificationPayload, } from './notification_center/type'; -export type { OptimizelyDecideOption } from './shared_types'; - export type { UserAttributeValue, UserAttributes, diff --git a/lib/index.lite.ts b/lib/index.lite.ts deleted file mode 100644 index ace83107d..000000000 --- a/lib/index.lite.ts +++ /dev/null @@ -1 +0,0 @@ -const msg = 'not used'; \ No newline at end of file diff --git a/lib/index.universal.ts b/lib/index.universal.ts new file mode 100644 index 000000000..5df959975 --- /dev/null +++ b/lib/index.universal.ts @@ -0,0 +1,115 @@ +/** + * Copyright 2025, 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 + * + * https://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. + */ +import { Client, Config } from './shared_types'; +import { getOptimizelyInstance } from './client_factory'; +import { JAVASCRIPT_CLIENT_ENGINE } from './utils/enums'; + +/** + * Creates an instance of the Optimizely class + * @param {Config} config + * @return {Client|null} the Optimizely client object + * null on error + */ +export const createInstance = function(config: Config): Client | null { + return getOptimizelyInstance(config); +}; + +export { createEventDispatcher } from './event_processor/event_dispatcher/event_dispatcher_factory'; + +export { createPollingProjectConfigManager } from './project_config/config_manager_factory.universal'; + +export { createForwardingEventProcessor, createBatchEventProcessor } from './event_processor/event_processor_factory.universal'; + +// TODO: decide on universal odp manager factory interface +// export { createOdpManager } from './odp/odp_manager_factory.node'; +// export { createVuidManager } from './vuid/vuid_manager_factory.node'; + +export * from './common_exports'; + +export const clientEngine: string = JAVASCRIPT_CLIENT_ENGINE; + +// type exports +export type { RequestHandler } from './utils/http_request_handler/http'; + +// config manager related types +export type { + StaticConfigManagerConfig, + OpaqueConfigManager, +} from './project_config/config_manager_factory'; + +export type { UniversalPollingConfigManagerConfig } from './project_config/config_manager_factory.universal'; + +// event processor related types +export type { + LogEvent, + EventDispatcherResponse, + EventDispatcher, +} from './event_processor/event_dispatcher/event_dispatcher'; + +export type { UniversalBatchEventProcessorOptions } from './event_processor/event_processor_factory.universal'; + +export type { + OpaqueEventProcessor, +} from './event_processor/event_processor_factory'; + +// Logger related types +export type { + LogHandler, +} from './logging/logger'; + +export type { + OpaqueLevelPreset, + LoggerConfig, + OpaqueLogger, +} from './logging/logger_factory'; + +// Error related types +export type { ErrorHandler } from './error/error_handler'; +export type { OpaqueErrorNotifier } from './error/error_notifier_factory'; + +export type { Cache } from './utils/cache/cache'; + +export type { + NotificationType, + NotificationPayload, +} from './notification_center/type'; + +export type { + UserAttributeValue, + UserAttributes, + OptimizelyConfig, + FeatureVariableValue, + OptimizelyVariable, + OptimizelyVariation, + OptimizelyExperiment, + OptimizelyFeature, + OptimizelyDecisionContext, + OptimizelyForcedDecision, + EventTags, + Event, + DatafileOptions, + UserProfileService, + UserProfile, + ListenerPayload, + OptimizelyDecision, + OptimizelyUserContext, + Config, + Client, + ActivateListenerPayload, + TrackListenerPayload, + NotificationCenter, + OptimizelySegmentOption, +} from './shared_types'; diff --git a/lib/project_config/config_manager_factory.universal.ts b/lib/project_config/config_manager_factory.universal.ts new file mode 100644 index 000000000..bcbd4a310 --- /dev/null +++ b/lib/project_config/config_manager_factory.universal.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2025, 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 + * + * https://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. + */ + +import { getOpaquePollingConfigManager, OpaqueConfigManager, PollingConfigManagerConfig } from "./config_manager_factory"; +import { NodeRequestHandler } from "../utils/http_request_handler/request_handler.node"; +import { ProjectConfigManager } from "./project_config_manager"; +import { DEFAULT_URL_TEMPLATE, DEFAULT_AUTHENTICATED_URL_TEMPLATE } from './constant'; +import { RequestHandler } from "../utils/http_request_handler/http"; + +export type UniversalPollingConfigManagerConfig = PollingConfigManagerConfig & { + requestHandler: RequestHandler; +} + +export const createPollingProjectConfigManager = (config: UniversalPollingConfigManagerConfig): OpaqueConfigManager => { + const defaultConfig = { + autoUpdate: true, + }; + return getOpaquePollingConfigManager({ ...defaultConfig, ...config }); +}; diff --git a/package.json b/package.json index 7df6c1b51..ef0830b7e 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "import": "./dist/index.react_native.es.min.js", "require": "./dist/index.react_native.min.js" }, - "./lite": { + "./universal": { "types": "./dist/index.lite.d.ts", "node": "./dist/index.lite.min.js", "import": "./dist/index.lite.es.js", diff --git a/rollup.config.js b/rollup.config.js index 046cdab1e..2fc077a83 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -141,11 +141,11 @@ const bundles = { 'cjs-node-min': cjsBundleFor('node'), 'cjs-browser-min': cjsBundleFor('browser'), 'cjs-react-native-min': cjsBundleFor('react_native'), - 'cjs-lite': cjsBundleFor('lite'), + 'cjs-universal': cjsBundleFor('universal'), 'esm-browser-min': esmBundleFor('browser'), 'esm-node-min': esmBundleFor('node', { ext: '.mjs' }), 'esm-react-native-min': esmBundleFor('react_native'), - 'esm-lite': esmBundleFor('lite'), + 'esm-universal': esmBundleFor('universal'), 'json-schema': jsonSchemaBundle, umd: umdBundle, }; From 1f43271bee16e2bd4265302a83ebaeff5ee6bb2e Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Tue, 25 Feb 2025 01:54:12 +0600 Subject: [PATCH 2/2] upd --- .../event_dispatcher/event_dispatcher_factory.ts | 16 ++++++++++++++++ package.json | 7 +++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts b/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts index 9df8515c5..035fb7e49 100644 --- a/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts +++ b/lib/event_processor/event_dispatcher/event_dispatcher_factory.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2025, 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 + * + * https://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. + */ + import { RequestHandler } from '../../utils/http_request_handler/http'; import { DefaultEventDispatcher } from './default_dispatcher'; import { EventDispatcher } from './event_dispatcher'; diff --git a/package.json b/package.json index ef0830b7e..525302c6a 100644 --- a/package.json +++ b/package.json @@ -43,10 +43,9 @@ "require": "./dist/index.react_native.min.js" }, "./universal": { - "types": "./dist/index.lite.d.ts", - "node": "./dist/index.lite.min.js", - "import": "./dist/index.lite.es.js", - "default": "./dist/index.lite.min.js" + "types": "./dist/index.universal.d.ts", + "import": "./dist/index.universal.es.min.js", + "require": "./dist/index.universal.min.js" } }, "scripts": {