From 5a532c1c152e252b3c25e4ef0eb5bb17de3f3e01 Mon Sep 17 00:00:00 2001 From: Md Junaed Hossain <169046794+junaed-optimizely@users.noreply.github.com> Date: Tue, 22 Apr 2025 21:55:27 +0600 Subject: [PATCH 1/9] [FSSDK-11403] init doc update --- README.md | 108 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 86d82035c..f20a1dfbe 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ In addition, other environments are likely compatible but are not formally suppo ### Requirements -* JavaScript (Browser): Modern web browser that is ES5-compliant. +* JavaScript (Browser): Modern web browser that is ES6-compliant. * JavaScript (Node): Node 16.0.0+ @@ -70,11 +70,44 @@ Using `deno` (no installation required): ```javascript import optimizely from "npm:@optimizely/optimizely-sdk" ``` -## Use the JavaScript SDK (Browser) +## Use the JavaScript SDK -See the [Optimizely Feature Experimentation developer documentation for JavaScript (Browser)](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/javascript-sdk) to learn how to set up your first JavaScript project and use the SDK for client-side applications. +See the [Optimizely Feature Experimentation developer documentation for JavaScript](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/javascript-sdk) to learn how to set up your first JavaScript project and use the SDK for client-side applications. -### Initialization (Browser) +### Initialization (Using NPM) + +```javascript +import { + createInstance, + createPollingProjectConfigManager, + createBatchEventProcessor, + createOdpManager, +} from "@optimizely/optimizely-sdk"; + + +const pollingConfigManager = createPollingProjectConfigManager({ + sdkKey: "", +}) +const batchEventProcessor = createBatchEventProcessor() +const odpManager = createOdpManager() + +const optimizelyClient = createInstance({ + projectConfigManager: pollingConfigManager, + eventProcessor: batchEventProcessor, + odpManager: odpManager, +}) + +if(optimizelyClient) { + optimizelyClient.onReady().then(() => { + console.log("Optimizely client is ready"); + }).catch((error) => { + console.error("Error initializing Optimizely client:", error); + }); +} + +``` + +### Initialization (Using HTML) The package has different entry points for different environments. The browser entry point is an ES module, which can be used with an appropriate bundler like **Webpack** or **Rollup**. Additionally, for ease of use during initial evaluations you can include a standalone umd bundle of the SDK in your web page by fetching it from [unpkg](https://unpkg.com/): @@ -89,45 +122,38 @@ When evaluated, that bundle assigns the SDK's exports to `window.optimizelySdk`. As `window.optimizelySdk` should be a global variable at this point, you can continue to use it like so: -```javascript -const optimizelyClient = window.optimizelySdk.createInstance({ - sdkKey: '', - // datafile: window.optimizelyDatafile, - // etc. -}); - -optimizelyClient.onReady().then(({ success, reason }) => { - if (success) { - // Create the Optimizely user context, make decisions, and more here! - } -}); +```html + ``` -Regarding `EventDispatcher`s: In Node.js and browser environments, the default `EventDispatcher` is powered by the [`http/s`](https://nodejs.org/api/http.html) modules and by [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Browser_compatibility), respectively. In all other environments, you must supply your own `EventDispatcher`. -## Use the JavaScript SDK (Node) - -See the [Optimizely Feature Experimentation developer documentation for JavaScript (Node)](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/javascript-node-sdk) to learn how to set up your first JavaScript project and use the SDK for server-side applications. - -### Initialization (Node) - -The package has different entry points for different environments. The node entry point is CommonJS module. - -```javascript -const optimizelySdk = require('@optimizely/optimizely-sdk'); - -const optimizelyClient = optimizelySdk.createInstance({ - sdkKey: '', - // datafile: window.optimizelyDatafile, - // etc. -}); - -optimizelyClient.onReady().then(({ success, reason }) => { - if (success) { - // Create the Optimizely user context, make decisions, and more here! - } -}); -``` Regarding `EventDispatcher`s: In Node.js environment, the default `EventDispatcher` is powered by the [`http/s`](https://nodejs.org/api/http.html) module. @@ -207,4 +233,4 @@ First-party code (under `packages/optimizely-sdk/lib/`, `packages/datafile-manag - Ruby - https://github.com/optimizely/ruby-sdk -- Swift - https://github.com/optimizely/swift-sdk \ No newline at end of file +- Swift - https://github.com/optimizely/swift-sdk From df289b22877fad03cc2c6d75fd5fac43d5828cab Mon Sep 17 00:00:00 2001 From: Md Junaed Hossain <169046794+junaed-optimizely@users.noreply.github.com> Date: Mon, 19 May 2025 19:11:02 +0600 Subject: [PATCH 2/9] [FSSDK-11403] migration guide addition --- MIGRATION.md | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 96 +++++++---- 2 files changed, 522 insertions(+), 34 deletions(-) create mode 100644 MIGRATION.md diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 000000000..d8a881e48 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,460 @@ +# Migrating v5 to v6 + +This guide will help you migrate your implementation from Optimizely JavaScript SDK v5 to v6. The new version introduces several architectural changes that provide more flexibility and control over SDK components. + +## Table of Contents + +1. [Major Changes](#major-changes) +2. [Client Initialization](#client-initialization) +3. [Project Configuration Management](#project-configuration-management) +4. [Event Processing](#event-processing) +5. [ODP Management](#odp-management) +6. [VUID Management](#vuid-management) +7. [Error Handling](#error-handling) +8. [Logging](#logging) +9. [onReady Promise Behavior](#onready-promise-behavior) +10. [Dispose of Client](#dispose-of-client) +11. [Migration Examples](#migration-examples) + +## Major Changes + +In v6, the SDK architecture has been modularized to give you more control over different components: + +- The monolithic `createInstance` call is now split into multiple factory functions +- Project configuration management is now configurable through dedicated components +- Event processing has dedicated implementations for different use cases +- ODP and VUID management are separate components +- Logger and error handler are created through factory functions + +## Client Initialization + +### v5 (Before) + +```javascript +import { createInstance } from '@optimizely/optimizely-sdk'; + +const optimizely = createInstance({ + sdkKey: '', + datafile: datafile, // optional + datafileOptions: { + autoUpdate: true, + updateInterval: 300000, // 5 minutes + }, + eventBatchSize: 10, + eventFlushInterval: 1000, + logLevel: LogLevel.DEBUG, + errorHandler: { handleError: (error) => console.error(error) }, + odpOptions: { + disabled: false, + segmentsCacheSize: 100, + segmentsCacheTimeout: 600000, // 10 minutes + } +}); +``` + +### v6 (After) + +```javascript +import { + createInstance, + createPollingProjectConfigManager, + createBatchEventProcessor, + createOdpManager, + createVuidManager, + createLogger, + createErrorNotifier, + DEBUG +} from "@optimizely/optimizely-sdk"; + +// Create a project config manager +const projectConfigManager = createPollingProjectConfigManager({ + sdkKey: '', + datafile: datafile, // optional + autoUpdate: true, + updateInterval: 300000, // 5 minutes in milliseconds +}); + +// Create an event processor +const eventProcessor = createBatchEventProcessor({ + batchSize: 10, + flushInterval: 1000, +}); + +// Create an ODP manager +const odpManager = createOdpManager({ + segmentsCacheSize: 100, + segmentsCacheTimeout: 600000, // 10 minutes +}); + +// Create a VUID manager (optional) +const vuidManager = createVuidManager({ + enableVuid: true +}); + +// Create a logger +const logger = createLogger({ + level: DEBUG +}); + +// Create an error notifier +const errorNotifier = createErrorNotifier({ + handleError: (error) => console.error(error) +}); + +// Create the Optimizely client instance +const optimizely = createInstance({ + projectConfigManager, + eventProcessor, + odpManager, + vuidManager, + logger, + errorNotifier +}); +``` + +## Project Configuration Management + +In v6, datafile management is handled by a dedicated Project Config Manager. Choose either: + +### Polling Project Config Manager + +For automatic datafile updates: + +```javascript +const projectConfigManager = createPollingProjectConfigManager({ + sdkKey: '', + datafile: datafileString, // optional + autoUpdate: true, + updateInterval: 60000, // 1 minute + urlTemplate: 'https://custom-cdn.com/datafiles/%s.json' // optional +}); +``` + +### Static Project Config Manager + +When you want to manage datafile updates manually: + +```javascript +const projectConfigManager = createStaticProjectConfigManager({ + datafile: datafileString, +}); +``` + +## Event Processing + +v6 provides two types of event processors: + +### Batch Event Processor + +Queues events and sends them in batches: + +```javascript +const batchEventProcessor = createBatchEventProcessor({ + batchSize: 10, // default + flushInterval: 1000, // default for browser + eventDispatcher: customEventDispatcher, // optional +}); +``` + +### Forwarding Event Processor + +Sends events immediately: + +```javascript +const forwardingEventProcessor = createForwardingEventProcessor({ + eventDispatcher: customEventDispatcher, // optional +}); +``` + +## ODP Management + +In v5, ODP functionality was configured via `odpOptions`. In v6, use the dedicated ODP Manager: + +### v5 (Before) + +```javascript +const optimizely = createInstance({ + sdkKey: '', + odpOptions: { + disabled: false, + segmentsCacheSize: 100, + segmentsCacheTimeout: 600000, // 10 minutes + eventApiTimeout: 1000, + segmentsApiTimeout: 1000, + } +}); +``` + +### v6 (After) + +```javascript +const odpManager = createOdpManager({ + segmentsCacheSize: 100, + segmentsCacheTimeout: 600000, // 10 minutes + eventApiTimeout: 1000, + segmentsApiTimeout: 1000, + eventBatchSize: 5, // Now configurable in browser + eventFlushInterval: 3000, // Now configurable in browser +}); + +const optimizely = createInstance({ + projectConfigManager, + odpManager +}); +``` + +To disable ODP functionality in v6, simply don't provide an ODP Manager to the client instance. + +## VUID Management + +In v6, VUID tracking is disabled by default and must be explicitly enabled: + +```javascript +const vuidManager = createVuidManager({ + enableVuid: true, // Explicitly enable VUID tracking +}); + +const optimizely = createInstance({ + projectConfigManager, + vuidManager +}); +``` + +To access the VUID in v6, use the VUID manager directly: + +```javascript +// v5 +const vuid = optimizely.getVuid(); + +// v6 +const vuid = vuidManager.getVuid(); +``` + +## Error Handling + +Error handling in v6 uses a new error notifier pattern: + +### v5 (Before) + +```javascript +const optimizely = createInstance({ + errorHandler: { + handleError: (error) => { + console.error("Custom error handler", error); + } + } +}); +``` + +### v6 (After) + +```javascript +const errorNotifier = createErrorNotifier({ + handleError: (error) => { + console.error("Custom error handler", error); + } +}); + +const optimizely = createInstance({ + projectConfigManager, + errorNotifier +}); +``` + +## Logging + +Logging in v6 uses a dedicated logger created via a factory function: + +### v5 (Before) + +```javascript +const optimizely = createInstance({ + logLevel: LogLevel.DEBUG +}); +``` + +### v6 (After) + +```javascript +import { createLogger, DEBUG } from "@optimizely/optimizely-sdk"; + +const logger = createLogger({ + level: DEBUG +}); + +const optimizely = createInstance({ + projectConfigManager, + logger +}); +``` + +## onReady Promise Behavior + +The `onReady()` method behavior has changed: + +### v5 (Before) + +```javascript +optimizely.onReady().then(({ success, reason }) => { + if (success) { + // optimizely is ready to use + } else { + console.log(`initialization unsuccessful: ${reason}`); + } +}); +``` + +### v6 (After) + +```javascript +optimizely + .onReady() + .then(() => { + // optimizely is ready to use + console.log("Client is ready"); + }) + .catch((err) => { + console.error("Error initializing Optimizely client:", err); + }); +``` + +## Dispose of Client + +Both versions require proper cleanup with the `close()` method. In v6, you can also make a client disposable: + +```javascript +// Create a disposable client (v6 only) +const optimizely = createInstance({ + projectConfigManager, + disposable: true +}); + +// Close the client (both v5 and v6) +optimizely.close(); +``` + +## Migration Examples + +### Basic Example with SDK Key + +#### v5 (Before) + +```javascript +import { createInstance } from '@optimizely/optimizely-sdk'; + +const optimizely = createInstance({ + sdkKey: '' +}); + +optimizely.onReady().then(({ success }) => { + if (success) { + // Use the client + } +}); +``` + +#### v6 (After) + +```javascript +import { + createInstance, + createPollingProjectConfigManager +} from '@optimizely/optimizely-sdk'; + +const projectConfigManager = createPollingProjectConfigManager({ + sdkKey: '' +}); + +const optimizely = createInstance({ + projectConfigManager +}); + +optimizely + .onReady() + .then(() => { + // Use the client + }) + .catch(err => { + console.error(err); + }); +``` + +### Complete Example with ODP and Event Batching + +#### v5 (Before) + +```javascript +import { createInstance, LogLevel } from '@optimizely/optimizely-sdk'; + +const optimizely = createInstance({ + sdkKey: '', + datafileOptions: { + autoUpdate: true, + updateInterval: 60000 // 1 minute + }, + eventBatchSize: 3, + eventFlushInterval: 10000, // 10 seconds + logLevel: LogLevel.DEBUG, + odpOptions: { + segmentsCacheSize: 10, + segmentsCacheTimeout: 60000 // 1 minute + } +}); + +optimizely.notificationCenter.addNotificationListener( + enums.NOTIFICATION_TYPES.TRACK, + (payload) => { + console.log("Track event", payload); + } +); +``` + +#### v6 (After) + +```javascript +import { + createInstance, + createPollingProjectConfigManager, + createBatchEventProcessor, + createOdpManager, + createLogger, + DEBUG, + NOTIFICATION_TYPES +} from '@optimizely/optimizely-sdk'; + +const projectConfigManager = createPollingProjectConfigManager({ + sdkKey: '', + autoUpdate: true, + updateInterval: 60000 // 1 minute +}); + +const batchEventProcessor = createBatchEventProcessor({ + batchSize: 3, + flushInterval: 10000, // 10 seconds +}); + +const odpManager = createOdpManager({ + segmentsCacheSize: 10, + segmentsCacheTimeout: 60000 // 1 minute +}); + +const logger = createLogger({ + level: DEBUG +}); + +const optimizely = createInstance({ + projectConfigManager, + eventProcessor: batchEventProcessor, + odpManager, + logger +}); + +optimizely.notificationCenter.addNotificationListener( + NOTIFICATION_TYPES.TRACK, + (payload) => { + console.log("Track event", payload); + } +); +``` + +For complete implementation examples, refer to the [Optimizely JavaScript SDK documentation](https://docs.developers.optimizely.com/feature-experimentation/docs/javascript-browser-sdk-v6). diff --git a/README.md b/README.md index f20a1dfbe..65dad49c0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Coveralls](https://img.shields.io/coveralls/optimizely/javascript-sdk.svg)](https://coveralls.io/github/optimizely/javascript-sdk) [![license](https://img.shields.io/github/license/optimizely/javascript-sdk.svg)](https://choosealicense.com/licenses/apache-2.0/) -This repository houses the JavaScript SDK for use with Optimizely Feature Experimentation and Optimizely Full Stack (legacy). +This repository houses the JavaScript SDK for use with Optimizely Feature Experimentation and Optimizely Full Stack (legacy). The SDK now features a modular architecture for greater flexibility and control. If you're upgrading from a previous version, see our [Migration Guide](MIGRATION.md). Optimizely Feature Experimentation is an A/B testing and feature management tool for product development teams that enables you to experiment at every step. Using Optimizely Feature Experimentation allows for every feature on your roadmap to be an opportunity to discover hidden insights. Learn more at [Optimizely.com](https://www.optimizely.com/products/experiment/feature-experimentation/), or see the [developer documentation](https://docs.developers.optimizely.com/feature-experimentation/docs/introduction). @@ -74,6 +74,8 @@ import optimizely from "npm:@optimizely/optimizely-sdk" See the [Optimizely Feature Experimentation developer documentation for JavaScript](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/javascript-sdk) to learn how to set up your first JavaScript project and use the SDK for client-side applications. +The SDK uses a modular architecture with dedicated components for project configuration, event processing, and more. The examples below demonstrate the recommended initialization pattern. + ### Initialization (Using NPM) ```javascript @@ -84,27 +86,40 @@ import { createOdpManager, } from "@optimizely/optimizely-sdk"; - +// 1. Configure your project config manager const pollingConfigManager = createPollingProjectConfigManager({ sdkKey: "", -}) -const batchEventProcessor = createBatchEventProcessor() -const odpManager = createOdpManager() + autoUpdate: true, // Optional: enable automatic updates + updateInterval: 300000, // Optional: update every 5 minutes (in ms) +}); + +// 2. Create an event processor for analytics +const batchEventProcessor = createBatchEventProcessor({ + batchSize: 10, // Optional: default batch size + flushInterval: 1000, // Optional: flush interval in ms +}); +// 3. Set up ODP manager for segments and audience targeting +const odpManager = createOdpManager(); + +// 4. Initialize the Optimizely client with the components const optimizelyClient = createInstance({ projectConfigManager: pollingConfigManager, eventProcessor: batchEventProcessor, odpManager: odpManager, -}) - -if(optimizelyClient) { - optimizelyClient.onReady().then(() => { - console.log("Optimizely client is ready"); - }).catch((error) => { - console.error("Error initializing Optimizely client:", error); - }); +}); + +// 5. Wait for the client to be ready before using +if (optimizelyClient) { + optimizelyClient.onReady() + .then(() => { + console.log("Optimizely client is ready"); + // Your application code using Optimizely goes here + }) + .catch((error) => { + console.error("Error initializing Optimizely client:", error); + }); } - ``` ### Initialization (Using HTML) @@ -124,32 +139,42 @@ As `window.optimizelySdk` should be a global variable at this point, you can con ```html ``` @@ -197,9 +222,12 @@ For more information regarding contributing to the Optimizely JavaScript SDK, pl ## Special Notes -### Migrating from 4.x.x +### Migration Guides + +If you're updating your SDK version, please check the appropriate migration guide: -This version represents a major version change and, as such, introduces some breaking changes. Please refer to the [Changelog](CHANGELOG.md#500---january-19-2024) for more details. +- **Migrating from 5.x to 6.x**: See our [Migration Guide](MIGRATION.md) for detailed instructions on updating to the new modular architecture. +- **Migrating from 4.x to 5.x**: Please refer to the [Changelog](CHANGELOG.md#500---january-19-2024) for details on these breaking changes. ### Feature Management access From 5a01392f904b6a68f0c79b36426515ac5c9849c3 Mon Sep 17 00:00:00 2001 From: Md Junaed Hossain <169046794+junaed-optimizely@users.noreply.github.com> Date: Wed, 28 May 2025 18:30:50 +0600 Subject: [PATCH 3/9] [FSSDK-11403] readme change --- README.md | 79 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index be0d99f09..8f26defd0 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Optimizely Rollouts is [free feature flags](https://www.optimizely.com/free-feat > For **Node.js** applications, refer to the [JavaScript (Node) variant of the developer documentation](https://docs.developers.optimizely.com/feature-experimentation/docs/javascript-node-sdk). > For **Edge Functions**, we provide starter kits that utilize the Optimizely JavaScript SDK for the following platforms: +> > - [Akamai (Edgeworkers)](https://github.com/optimizely/akamai-edgeworker-starter-kit) > - [AWS Lambda@Edge](https://github.com/optimizely/aws-lambda-at-edge-starter-kit) > - [Cloudflare Worker](https://github.com/optimizely/cloudflare-worker-template) @@ -32,38 +33,44 @@ Optimizely Rollouts is [free feature flags](https://www.optimizely.com/free-feat ### Prerequisites Ensure the SDK supports all of the platforms you're targeting. In particular, the SDK targets modern ES6-compliant JavaScript environments. We officially support: + - Node.js >= 18.0.0. By extension, environments like AWS Lambda, Google Cloud Functions, and Auth0 Webtasks are supported as well. Older Node.js releases likely work too (try `npm test` to validate for yourself), but are not formally supported. - Modern Web Browsers, such as Microsoft Edge 84+, Firefox 91+, Safari 13+, and Chrome 102+, Opera 76+ In addition, other environments are likely compatible but are not formally supported including: + - Progressive Web Apps, WebViews, and hybrid mobile apps like those built with React Native and Apache Cordova. - [Cloudflare Workers](https://developers.cloudflare.com/workers/) and [Fly](https://fly.io/), both of which are powered by recent releases of V8. - Anywhere else you can think of that might embed a JavaScript engine. The sky is the limit; experiment everywhere! 🚀 - ### Install the SDK Once you've validated that the SDK supports the platforms you're targeting, fetch the package from [NPM](https://www.npmjs.com/package/@optimizely/optimizely-sdk): Using `npm`: + ```sh npm install --save @optimizely/optimizely-sdk ``` Using `yarn`: + ```sh yarn add @optimizely/optimizely-sdk ``` Using `pnpm`: + ```sh pnpm add @optimizely/optimizely-sdk ``` Using `deno` (no installation required): + ```javascript -import optimizely from "npm:@optimizely/optimizely-sdk" +import optimizely from 'npm:@optimizely/optimizely-sdk'; ``` + ## Use the JavaScript SDK See the [Optimizely Feature Experimentation developer documentation for JavaScript](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/javascript-sdk) to learn how to set up your first JavaScript project and use the SDK for client-side applications. @@ -78,19 +85,19 @@ import { createPollingProjectConfigManager, createBatchEventProcessor, createOdpManager, -} from "@optimizely/optimizely-sdk"; +} from '@optimizely/optimizely-sdk'; // 1. Configure your project config manager const pollingConfigManager = createPollingProjectConfigManager({ - sdkKey: "", - autoUpdate: true, // Optional: enable automatic updates - updateInterval: 300000, // Optional: update every 5 minutes (in ms) + sdkKey: '', + autoUpdate: true, // Optional: enable automatic updates + updateInterval: 300000, // Optional: update every 5 minutes (in ms) }); // 2. Create an event processor for analytics const batchEventProcessor = createBatchEventProcessor({ - batchSize: 10, // Optional: default batch size - flushInterval: 1000, // Optional: flush interval in ms + batchSize: 10, // Optional: default batch size + flushInterval: 1000, // Optional: flush interval in ms }); // 3. Set up ODP manager for segments and audience targeting @@ -103,20 +110,18 @@ const optimizelyClient = createInstance({ odpManager: odpManager, }); -// 5. Wait for the client to be ready before using -if (optimizelyClient) { - optimizelyClient.onReady() - .then(() => { - console.log("Optimizely client is ready"); - // Your application code using Optimizely goes here - }) - .catch((error) => { - console.error("Error initializing Optimizely client:", error); - }); -} +optimizelyClient + .onReady() + .then(() => { + console.log('Optimizely client is ready'); + // Your application code using Optimizely goes here + }) + .catch(error => { + console.error('Error initializing Optimizely client:', error); + }); ``` -### Initialization (Using HTML) +### Initialization (Using HTML) The package has different entry points for different environments. The browser entry point is an ES module, which can be used with an appropriate bundler like **Webpack** or **Rollup**. Additionally, for ease of use during initial evaluations you can include a standalone umd bundle of the SDK in your web page by fetching it from [unpkg](https://unpkg.com/): @@ -138,42 +143,38 @@ As `window.optimizelySdk` should be a global variable at this point, you can con createInstance, createPollingProjectConfigManager, createBatchEventProcessor, - createOdpManager + createOdpManager, } = window.optimizelySdk; // Initialize components const pollingConfigManager = createPollingProjectConfigManager({ - sdkKey: "", - autoUpdate: true + sdkKey: '', + autoUpdate: true, }); - + const batchEventProcessor = createBatchEventProcessor(); - + const odpManager = createOdpManager(); // Create the Optimizely client const optimizelyClient = createInstance({ projectConfigManager: pollingConfigManager, eventProcessor: batchEventProcessor, - odpManager: odpManager + odpManager: odpManager, }); - // Wait for initialization to complete - if (optimizelyClient) { - optimizelyClient.onReady() - .then(() => { - console.log("Optimizely client is ready"); - // Start using the client here - }) - .catch((error) => { - console.error("Error initializing Optimizely client:", error); - }); - } + optimizelyClient + .onReady() + .then(() => { + console.log('Optimizely client is ready'); + // Start using the client here + }) + .catch(error => { + console.error('Error initializing Optimizely client:', error); + }); ``` - - Regarding `EventDispatcher`s: In Node.js environment, the default `EventDispatcher` is powered by the [`http/s`](https://nodejs.org/api/http.html) module. ## SDK Development From 68f551de21b9f81f97d8f8a55672dc361d12e170 Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Wed, 28 May 2025 19:38:43 +0600 Subject: [PATCH 4/9] update migration guide --- MIGRATION.md | 81 ++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index d8a881e48..afa7dba2f 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -21,10 +21,9 @@ This guide will help you migrate your implementation from Optimizely JavaScript In v6, the SDK architecture has been modularized to give you more control over different components: - The monolithic `createInstance` call is now split into multiple factory functions -- Project configuration management is now configurable through dedicated components -- Event processing has dedicated implementations for different use cases -- ODP and VUID management are separate components -- Logger and error handler are created through factory functions +- Core functionality (project configuration, event processing, ODP, VUID, logging, and error handling) is now configured through dedicated components created via factory functions, giving you greater flexibility and control in enabling/disabling certain components and allowing optimizing the bundle size for frontend projects. +- Event dispatcher interface has been updated to use Promises +- onReady Promise Behavior has changed ## Client Initialization @@ -132,7 +131,7 @@ const projectConfigManager = createPollingProjectConfigManager({ ### Static Project Config Manager -When you want to manage datafile updates manually: +When you want to manage datafile updates manually or want to use a fixed datafile: ```javascript const projectConfigManager = createStaticProjectConfigManager({ @@ -142,7 +141,9 @@ const projectConfigManager = createStaticProjectConfigManager({ ## Event Processing -v6 provides two types of event processors: +In v5, a batch event processor was enabled by default. In v6, an event processor must be instantiated and passed in +explicitly to `createInstance` via the `eventProcessor` option to enable event processing, otherwise no events will +be dispatched. v6 provides two types of event processors: ### Batch Event Processor @@ -150,8 +151,8 @@ Queues events and sends them in batches: ```javascript const batchEventProcessor = createBatchEventProcessor({ - batchSize: 10, // default - flushInterval: 1000, // default for browser + batchSize: 10, // optional, default is 10 + flushInterval: 1000, // optional, default 1000 for browser eventDispatcher: customEventDispatcher, // optional }); ``` @@ -166,9 +167,38 @@ const forwardingEventProcessor = createForwardingEventProcessor({ }); ``` +### Custom event dispatcher +The `EventDispatcher` interface has been updated so that the `dispatchEvent` method returns a Promise instead of calling a callback. + +In v5 (Before): + +```javascript +export type EventDispatcherResponse = { + statusCode: number +} + +export type EventDispatcherCallback = (response: EventDispatcherResponse) => void + +export interface EventDispatcher { + dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void +} +``` + +In v6(After): + +```javascript +export type EventDispatcherResponse = { + statusCode?: number +} + +export interface EventDispatcher { + dispatchEvent(event: LogEvent): Promise +} +``` + ## ODP Management -In v5, ODP functionality was configured via `odpOptions`. In v6, use the dedicated ODP Manager: +In v5, ODP functionality was configured via `odpOptions` and enabled by default. In v6, instantiate an OdpManager and pass to `createInstance` to enable ODP: ### v5 (Before) @@ -207,7 +237,7 @@ To disable ODP functionality in v6, simply don't provide an ODP Manager to the c ## VUID Management -In v6, VUID tracking is disabled by default and must be explicitly enabled: +In v6, VUID tracking is disabled by default and must be explicitly enabled by createing a vuidManager with `enableVuid` set to `true` and passing it to `createInstance`: ```javascript const vuidManager = createVuidManager({ @@ -220,19 +250,9 @@ const optimizely = createInstance({ }); ``` -To access the VUID in v6, use the VUID manager directly: - -```javascript -// v5 -const vuid = optimizely.getVuid(); - -// v6 -const vuid = vuidManager.getVuid(); -``` - ## Error Handling -Error handling in v6 uses a new error notifier pattern: +Error handling in v6 uses a new errorNotifier object: ### v5 (Before) @@ -263,7 +283,7 @@ const optimizely = createInstance({ ## Logging -Logging in v6 uses a dedicated logger created via a factory function: +Logging in v6 is disabled by defualt, and must be enabled by passing in a logger created via a factory function: ### v5 (Before) @@ -290,7 +310,7 @@ const optimizely = createInstance({ ## onReady Promise Behavior -The `onReady()` method behavior has changed: +The `onReady()` method behavior has changed in v6. In v5, onReady() fulfilled with an object that had two fields: `success` and `reason`. If the instance failed to initialize, `success` would be `false` and `reason` will contain an error message. In v6, if onReady() fulfills, that means the instance is ready to use, the fulfillment value is of unknown type and need not to be inspected. If the promise rejects, that means there was an error during initialization. ### v5 (Before) @@ -318,21 +338,6 @@ optimizely }); ``` -## Dispose of Client - -Both versions require proper cleanup with the `close()` method. In v6, you can also make a client disposable: - -```javascript -// Create a disposable client (v6 only) -const optimizely = createInstance({ - projectConfigManager, - disposable: true -}); - -// Close the client (both v5 and v6) -optimizely.close(); -``` - ## Migration Examples ### Basic Example with SDK Key From 9c5cfd575ea8beb2e8fde7e3df477593a464edc7 Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Wed, 28 May 2025 19:51:12 +0600 Subject: [PATCH 5/9] upd --- MIGRATION.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index afa7dba2f..705657f02 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -23,7 +23,7 @@ In v6, the SDK architecture has been modularized to give you more control over d - The monolithic `createInstance` call is now split into multiple factory functions - Core functionality (project configuration, event processing, ODP, VUID, logging, and error handling) is now configured through dedicated components created via factory functions, giving you greater flexibility and control in enabling/disabling certain components and allowing optimizing the bundle size for frontend projects. - Event dispatcher interface has been updated to use Promises -- onReady Promise Behavior has changed +- onReady Promise behavior has changed ## Client Initialization @@ -113,7 +113,7 @@ const optimizely = createInstance({ ## Project Configuration Management -In v6, datafile management is handled by a dedicated Project Config Manager. Choose either: +In v6, datafile management must be configured by passing in a `projectConfigManager`. Choose either: ### Polling Project Config Manager @@ -153,7 +153,6 @@ Queues events and sends them in batches: const batchEventProcessor = createBatchEventProcessor({ batchSize: 10, // optional, default is 10 flushInterval: 1000, // optional, default 1000 for browser - eventDispatcher: customEventDispatcher, // optional }); ``` @@ -162,13 +161,11 @@ const batchEventProcessor = createBatchEventProcessor({ Sends events immediately: ```javascript -const forwardingEventProcessor = createForwardingEventProcessor({ - eventDispatcher: customEventDispatcher, // optional -}); +const forwardingEventProcessor = createForwardingEventProcessor(); ``` ### Custom event dispatcher -The `EventDispatcher` interface has been updated so that the `dispatchEvent` method returns a Promise instead of calling a callback. +In both v5 and v6, custom event dispatchers must implement the `EventDispatcher` interface. In v5, the `EventDispatcher` interface has been updated so that the `dispatchEvent` method returns a Promise instead of calling a callback. In v5 (Before): From b1dc7320d88692d172051b23baed2afee419d7f4 Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Wed, 28 May 2025 19:53:25 +0600 Subject: [PATCH 6/9] createInstance return null --- MIGRATION.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index 705657f02..9cf36bc01 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -111,6 +111,8 @@ const optimizely = createInstance({ }); ``` +In case an invalid config is passed to `createInstance`, it returned `null` in v5. In v6, it will throw and error instead of returning null. + ## Project Configuration Management In v6, datafile management must be configured by passing in a `projectConfigManager`. Choose either: From dc97220129411da1f90b1bc2ad4d94ae6a1f57a1 Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Wed, 28 May 2025 19:54:17 +0600 Subject: [PATCH 7/9] typo --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index 9cf36bc01..c7c457e49 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -111,7 +111,7 @@ const optimizely = createInstance({ }); ``` -In case an invalid config is passed to `createInstance`, it returned `null` in v5. In v6, it will throw and error instead of returning null. +In case an invalid config is passed to `createInstance`, it returned `null` in v5. In v6, it will throw an error instead of returning null. ## Project Configuration Management From 640d18fac359b546ecf2bbc1c8f7b994ac875ea8 Mon Sep 17 00:00:00 2001 From: Raju Ahmed Date: Wed, 28 May 2025 19:55:42 +0600 Subject: [PATCH 8/9] up --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index c7c457e49..d462c7d66 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -167,7 +167,7 @@ const forwardingEventProcessor = createForwardingEventProcessor(); ``` ### Custom event dispatcher -In both v5 and v6, custom event dispatchers must implement the `EventDispatcher` interface. In v5, the `EventDispatcher` interface has been updated so that the `dispatchEvent` method returns a Promise instead of calling a callback. +In both v5 and v6, custom event dispatchers must implement the `EventDispatcher` interface. In v6, the `EventDispatcher` interface has been updated so that the `dispatchEvent` method returns a Promise instead of calling a callback. In v5 (Before): From fde5e687cbb7413479f531e5bafe69a106dcb4cb Mon Sep 17 00:00:00 2001 From: Md Junaed Hossain <169046794+junaed-optimizely@users.noreply.github.com> Date: Thu, 29 May 2025 22:12:34 +0600 Subject: [PATCH 9/9] readme update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f26defd0..67ac9e583 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ See the [Optimizely Feature Experimentation developer documentation for JavaScri The SDK uses a modular architecture with dedicated components for project configuration, event processing, and more. The examples below demonstrate the recommended initialization pattern. -### Initialization (Using NPM) +### Initialization with Package Managers (npm, yarn, pnpm) ```javascript import {