Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// TODO: localForage/IndexedDB can store full objects.
// We can store the actual configObj, not the datafile, for fast initialization
import { makeGetRequest } from './browserRequest'
import HttpPollingDatafileManager from './httpPollingDatafileManager'
import { Headers, AbortableRequest, Response } from './http'
import { DatafileManagerConfig } from './datafileManager'
import { LocalForageShim, serialize, deserialize } from './localForageDatafileCache'
import DatafileCache from './datafileCache'
import { getLogger } from '@optimizely/js-sdk-logging'
const logger = getLogger('CachingDatafileManager')
export enum CacheRefreshDirective {
ONLY_IF_CACHE_MISS = 'ONLY_IF_CACHE_MISS',
YES_DONT_AWAIT = 'YES_DONT_AWAIT',
// TODO: The YES_WAIT option is equivalent to not using the cache, so it should be removed.
// Maybe this whole thing should be replaced with a boolean instead since there are only two valid options.
YES_AWAIT = 'YES_AWAIT',
}
// TODO: Add maxCacheAge
export interface BrowserCachingDatafileManagerConfig extends DatafileManagerConfig {
refreshDirective?: CacheRefreshDirective
}
export default class BrowserCachingDatafileManager extends HttpPollingDatafileManager {
private static localForageShim: LocalForageShim = new LocalForageShim()
* 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 { getLogger } from '@optimizely/js-sdk-logging'
import { AsyncStorage } from './storage'
import { DatafileCacheEntry, DatafileCacheEntrySerializer } from './datafileCacheEntry';
const logger = getLogger('DatafileManager')
// K is the type used in the storage interface
export default class DatafileStorage implements AsyncStorage {
private storage: AsyncStorage
private serializer: DatafileCacheEntrySerializer
constructor(storage: AsyncStorage, serializer: DatafileCacheEntrySerializer) {
this.storage = storage
this.serializer = serializer
}
async getItem(key: string): Promise {
const serializedEntry = await this.storage.getItem(key)
if (serializedEntry === null) {
return null
* 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.
*/
// TODO: Log messages should be debug level instead of error?
// TODO: Should it be a write-through cache (memory, then storage, etc.). Maybe this is overcomplicating things.
// TODO: Accepting serialize/deserialize FNs, maybe not the best. could try refactor.
// TODO: maxCacheAge parameter handling
import { getLogger } from '@optimizely/js-sdk-logging'
import { LOCAL_STORAGE_KEY_PREFIX } from './config'
import { DatafileCacheEntry, DeserializationResult } from './datafileCacheEntry'
const logger = getLogger('DatafileManager')
// K is the type returned by getItem and accepted by setItem
export interface AsyncStorage {
getItem(key: string): Promise
setItem(key: string, value: K): Promise
removeItem(key: string): Promise
}
// TODO: Refactor & share this logic for logging a maybe-error with same thing in httpPollingDatafileManager
function logError(maybeErr: any, messageTemplate: string): void {
if (maybeErr instanceof Error) {
logger.error(messageTemplate, maybeErr.message, maybeErr)
} else {
logger.error(messageTemplate, String(maybeErr))
}
}
* 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.
*/
// TODO change this to use Managed from js-sdk-models when available
import { objectValues } from '@optimizely/js-sdk-utils'
import {
BufferedEventDispatcher,
DispatchEntry,
EntryStatus,
} from './eventDispatcher'
import { getLogger } from '@optimizely/js-sdk-logging'
const logger = getLogger('EventProcessor')
const LS_KEY = 'optly_fs_event_queue'
export class BrowserEventDispatcher extends BufferedEventDispatcher {
start(): void {
super.start()
const data = window.localStorage.getItem(LS_KEY)
try {
if (data) {
const parsed = JSON.parse(data) as DispatchEntry[]
logger.info('flushing queue from previous session, num events = %s', parsed.length)
parsed.forEach((item: DispatchEntry) => {
this.enqueueAndDispatch(item, () => {})
})
}
} catch (e) {
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('promise-polyfill/dist/polyfill');
var logging = require('@optimizely/js-sdk-logging');
var fns = require('./utils/fns');
var configValidator = require('./utils/config_validator');
var defaultErrorHandler = require('./plugins/error_handler');
var defaultEventDispatcher = require('./plugins/event_dispatcher/index.browser');
var enums = require('./utils/enums');
var eventProcessor = require('@optimizely/js-sdk-event-processor');
var loggerPlugin = require('./plugins/logger');
var Optimizely = require('./optimizely');
var eventProcessorConfigValidator = require('./utils/event_processor_config_validator');
var logger = logging.getLogger();
logging.setLogHandler(loggerPlugin.createLogger());
logging.setLogLevel(logging.LogLevel.INFO);
var MODULE_NAME = 'INDEX_BROWSER';
var DEFAULT_EVENT_BATCH_SIZE = 10;
var DEFAULT_EVENT_FLUSH_INTERVAL = 1000; // Unit is ms, default is 1s
var hasRetriedEvents = false;
/**
* Entry point into the Optimizely Browser SDK
*/
module.exports = {
logging: loggerPlugin,
errorHandler: defaultErrorHandler,
eventDispatcher: defaultEventDispatcher,
* 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 { getLogger } from '@optimizely/js-sdk-logging'
// TODO change this to use Managed from js-sdk-models when available
import { Managed } from './managed'
const logger = getLogger('EventProcessor')
export type EventQueueSink = (buffer: K[]) => Promise
export interface EventQueue extends Managed {
enqueue(event: K): void
}
export interface EventQueueFactory {
createEventQueue(config: {
sink: EventQueueSink
flushInterval: number
maxQueueSize: number
}): EventQueue
}
class Timer {
*
* 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.
*/
var projectConfig = require('./');
var enums = require('../../utils/enums');
var testDatafile = require('../../tests/test_data');
var configValidator = require('../../utils/config_validator');
var logging = require('@optimizely/js-sdk-logging');
var logger = logging.getLogger();
var _ = require('lodash/core');
var fns = require('../../utils/fns');
var chai = require('chai');
var assert = chai.assert;
var loggerPlugin = require('../../plugins/logger');
var sinon = require('sinon');
var sprintf = require('@optimizely/js-sdk-utils').sprintf;
var ERROR_MESSAGES = enums.ERROR_MESSAGES;
var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES;
var LOG_LEVEL = enums.LOG_LEVEL;
describe('lib/core/project_config', function() {
var parsedAudiences = testDatafile.getParsedAudiences;
describe('createProjectConfig method', function() {
* 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 { AbortableRequest, Response, Headers } from './http'
import { REQUEST_TIMEOUT_MS } from './config'
import { getLogger } from '@optimizely/js-sdk-logging'
const logger = getLogger('DatafileManager')
const GET_METHOD = 'GET'
const READY_STATE_DONE = 4
function parseHeadersFromXhr(req: XMLHttpRequest): Headers {
const allHeadersString = req.getAllResponseHeaders()
if (allHeadersString === null) {
return {}
}
const headerLines = allHeadersString.split('\r\n')
const headers: Headers = {}
headerLines.forEach(headerLine => {
const separatorIndex = headerLine.indexOf(': ')
if (separatorIndex > -1) {
* 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.
*/
var fns = require('../../utils/fns');
var sprintf = require('@optimizely/js-sdk-utils').sprintf;
var logging = require('@optimizely/js-sdk-logging');
var configValidator = require('../../utils/config_validator');
var datafileManager = require('@optimizely/js-sdk-datafile-manager');
var enums = require('../../utils/enums');
var projectConfig = require('../../core/project_config');
var optimizelyConfig = require('../optimizely_config');
var logger = logging.getLogger();
var ERROR_MESSAGES = enums.ERROR_MESSAGES;
var MODULE_NAME = 'PROJECT_CONFIG_MANAGER';
/**
* Return an error message derived from a thrown value. If the thrown value is
* an error, return the error's message property. Otherwise, return a default
* provided by the second argument.
* @param {*} maybeError
* @param {String=} defaultMessage
* @return {String}
*/
function getErrorMessage(maybeError, defaultMessage) {
if (maybeError instanceof Error) {
return maybeError.message;
var logging = require('@optimizely/js-sdk-logging');
var attributesValidator = require('../../utils/attributes_validator');
var fns = require('../../utils/fns');
var eventTagUtils = require('../../utils/event_tag_utils');
var projectConfig = require('../project_config');
var CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom';
var logger = logging.getLogger('EVENT_BUILDER');
exports.buildImpressionEvent = function buildImpressionEvent(config) {
var configObj = config.configObj;
var experimentKey = config.experimentKey;
var variationKey = config.variationKey;
var userId = config.userId;
var userAttributes = config.userAttributes;
var clientEngine = config.clientEngine;
var clientVersion = config.clientVersion;
var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey);
var experimentId = projectConfig.getExperimentId(configObj, experimentKey);
var layerId = projectConfig.getLayerId(configObj, experimentId);
return {
type: 'impression',