UNPKG

rox-ssr

Version:

Rollout.io ROX JS SDK Client for SSR

244 lines 11.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rox = exports._RoxClient = exports.RoxOverridesPosition = exports.RoxFetcherStatus = exports.RoxNumber = exports.RoxString = exports.Flag = void 0; /* eslint-disable @typescript-eslint/naming-convention */ const utils_1 = require("./utils"); var flag_1 = require("./flag"); Object.defineProperty(exports, "Flag", { enumerable: true, get: function () { return flag_1.Flag; } }); var string_1 = require("./string"); Object.defineProperty(exports, "RoxString", { enumerable: true, get: function () { return string_1.RoxString; } }); var number_1 = require("./number"); Object.defineProperty(exports, "RoxNumber", { enumerable: true, get: function () { return number_1.RoxNumber; } }); var RoxFetcherStatus; (function (RoxFetcherStatus) { RoxFetcherStatus["AppliedFromEmbedded"] = "APPLIED_FROM_EMBEDDED"; RoxFetcherStatus["AppliedFromCache"] = "APPLIED_FROM_CACHE"; RoxFetcherStatus["AppliedFromNetwork"] = "APPLIED_FROM_NETWORK"; RoxFetcherStatus["ErrorFetchFailed"] = "ERROR_FETCH_FAILED"; })(RoxFetcherStatus = exports.RoxFetcherStatus || (exports.RoxFetcherStatus = {})); var RoxOverridesPosition; (function (RoxOverridesPosition) { RoxOverridesPosition["TopLeft"] = "top left"; RoxOverridesPosition["TopRight"] = "top right"; RoxOverridesPosition["BottomLeft"] = "bottom left"; RoxOverridesPosition["BottomRight"] = "bottom right"; })(RoxOverridesPosition = exports.RoxOverridesPosition || (exports.RoxOverridesPosition = {})); class _RoxClient { constructor() { /** * Dynamic API is an alternative to Rollout static API for defining flags on the * different container objects and accessing them from that container object. * https://support.rollout.io/docs/dynamic-api */ this.dynamicApi = utils_1.internalRox.dynamicApi; /** * Override: Should only be used for development purposes (QA - Feature dev - e2e) * * When you override an existing flag value using the Rox.overrides.setOverride method, * the SDK will disregard existing configuration coming from the dashboard and will * serialize the override on disk this value will be loaded and override the flag * right after you call Rox.setup. To clear the override from the cache you need to * call the Rox.overrides.clearOverride method. * * One can refer to the javascript-browser-api for this feature: * https://support.rollout.io/docs/javascript-browser-api#section--rox-overrides- */ this.overrides = utils_1.internalRox.overrides; // Helper boolean to check that setup() is not called more than once this.alreadyInitialized = false; this._configurationFetchedHandlers = []; this._rolloutData = {}; this._confFetchedHandlers = []; this._impressionHandlers = []; } register(namespace, roxContainer) { try { utils_1.internalRox.register(namespace, roxContainer); } catch (e) { if (!e.message || !e.message.includes('A namespace must be unique')) { // register failed for a reason other than namespace already existing throw e; } } // calling register multiple times is legitimate, but underlying SDK does not support it // Each webpack entrypoint actually gets its own instance // of Flags. However, the Rox singleton remains unique. // In this case, we rewrite the Flags with the values stored within Rox. if (this.flags && this.flags.length > 0) { this.flags.forEach((f) => { if (f === null || f === void 0 ? void 0 : f.name) { roxContainer[f.name.replace(`${namespace}.`, '')] = f; // eslint-disable-line no-param-reassign } }); } } setup(apiKey, options) { return __awaiter(this, void 0, void 0, function* () { if (this._initialSetup) { // this is a legitimate call only if parameters remain the same if (this._initialSetup.apiKey !== apiKey || this._initialSetup.devModeSecret !== (options === null || options === void 0 ? void 0 : options.devModeSecret)) { throw new Error('Rox cannot be initialized more than once'); } // Add the configurationFetchedHandler to the list of handlers // _configurationFetchedHandlers can only grow but this is not a memory leak; there can // only be a finite number of entry points if (options === null || options === void 0 ? void 0 : options.configurationFetchedHandler) { this._confFetchedHandlers.push(options.configurationFetchedHandler); } if (options === null || options === void 0 ? void 0 : options.impressionHandler) { this._impressionHandlers.push(options.impressionHandler); } return; } const _options = Object.assign({}, options); if (options === null || options === void 0 ? void 0 : options.configurationFetchedHandler) { this._confFetchedHandlers.push(options.configurationFetchedHandler); } _options.configurationFetchedHandler = this._confFetchedHandler; _options.impressionHandler = this._impressionsHandler; yield this._setup(apiKey, options); this._initialSetup = { apiKey, devModeSecret: options === null || options === void 0 ? void 0 : options.devModeSecret, }; }); } _confFetchedHandler() { const handlers = this._confFetchedHandlers; return (fetcherResults) => { handlers.forEach((cfh) => cfh(fetcherResults)); }; } _impressionsHandler() { const handlers = this._impressionHandlers; return (reporting, context) => { handlers.forEach((imh) => imh(reporting, context)); }; } /** * Initiate connection with Rox servers for the application identified by the application key. * The registered containers will be synced and Rox entities will get the appropriate values. * * https://support.rollout.io/docs/nodejs-api#section-setup */ _setup(apiKey, options) { return __awaiter(this, void 0, void 0, function* () { if (this.alreadyInitialized) { throw new Error('Rox cannot be initialized more than once'); } const _options = Object.assign({}, options); // @ts-ignore if ((0, utils_1.isBrowser)() && window && window.rolloutData) { // @ts-ignore Object.assign(_options, options, { embedded: window.rolloutData, disableNetworkFetch: true, }); if (_options.disablePushUpdateListener !== false) { _options.disablePushUpdateListener = true; } } if (!_options.platform) { _options.platform = 'SSR'; } if (options === null || options === void 0 ? void 0 : options.configurationFetchedHandler) { this._configurationFetchedHandlers.push(options.configurationFetchedHandler); } _options.configurationFetchedHandler = this._configurationFetchedHandler(); yield utils_1.internalRox.setup(apiKey, _options); this.alreadyInitialized = true; }); } /** * Set Global Context. * You can think of Global Context as a default context * * https://support.rollout.io/docs/nodejs-api#section-setcontext */ setContext(globalContext) { utils_1.internalRox.setContext(globalContext); } setCustomNumberProperty(name, value) { utils_1.internalRox.setCustomNumberProperty(name, value); } setCustomStringProperty(name, value) { utils_1.internalRox.setCustomStringProperty(name, value); } setCustomBooleanProperty(name, value) { utils_1.internalRox.setCustomBooleanProperty(name, value); } setCustomDateProperty(name, value) { utils_1.internalRox.setCustomDateProperty(name, value); } setCustomSemverProperty(name, value) { utils_1.internalRox.setCustomSemverProperty(name, value); } /** * Pulls the latest configuration and flag values down from the Rollout servers * * https://support.rollout.io/docs/nodejs-api#section-fetch */ fetch() { utils_1.internalRox.fetch(); } /** * Opens the flag override view, providing a debug UI for the application's set of * feature flags. * This is only available in a browser context * https://support.rollout.io/docs/javascript-browser-api#section-showoverrides */ showOverrides(position) { if ((0, utils_1.isBrowser)()) { utils_1.internalRox.showOverrides(position); return; } throw new Error('showOverrides is only available in a browser context'); } _configurationFetchedHandler() { // eslint-disable-next-line @typescript-eslint/no-this-alias const roxClient = this; return (fetcherResults) => { if (fetcherResults.hasChanges) { roxClient._rolloutData = fetcherResults.clientData; } roxClient._configurationFetchedHandlers.forEach((cfh) => cfh(fetcherResults)); }; } /** * The Rollout configuration data. This is intended to be called on the server side * and passed to the browser to hydrate Rollout's configuration data on browser side. * @example React example * import {Rox} from 'rox-ssr'; * // ... * // Your component render() method * render() { * return ( * <html> * <head> * <script type='text/javascript' * dangerouslySetInnerHTML={{ __html: `window.rolloutData = ${Rox.rolloutData};` }} /> * <head> * </html>) * } */ get rolloutData() { return JSON.stringify(this._rolloutData); } get flags() { return utils_1.internalRox.flags; } } exports._RoxClient = _RoxClient; exports.Rox = new _RoxClient(); //# sourceMappingURL=index.js.map