@@ -18,8 +18,8 @@ import { sprintf, objectValues } from '@optimizely/js-sdk-utils';
1818import { assign , keyBy } from '../../utils/fns' ;
1919import {
2020 ERROR_MESSAGES ,
21- LOG_MESSAGES ,
2221 LOG_LEVEL ,
22+ LOG_MESSAGES ,
2323 FEATURE_VARIABLE_TYPES ,
2424} from '../../utils/enums' ;
2525import configValidator from '../../utils/config_validator' ;
@@ -58,11 +58,14 @@ function createMutationSafeDatafileCopy(datafile) {
5858
5959/**
6060 * Creates projectConfig object to be used for quick project property lookup
61- * @param {Object } datafile JSON datafile representing the project
62- * @return {Object } Object representing project configuration
61+ * @param {Object } datafileObj JSON datafile representing the project
62+ * @param {string= } datafileStr JSON string representation of the datafile
63+ * @return {Object } Object representing project configuration
6364 */
64- export var createProjectConfig = function ( datafile ) {
65- var projectConfig = createMutationSafeDatafileCopy ( datafile ) ;
65+ export var createProjectConfig = function ( datafileObj , datafileStr = null ) {
66+ var projectConfig = createMutationSafeDatafileCopy ( datafileObj ) ;
67+
68+ projectConfig . __datafileStr = datafileStr === null ? JSON . stringify ( datafileObj ) : datafileStr ;
6669
6770 /*
6871 * Conditions of audiences in projectConfig.typedAudiences are not
@@ -512,7 +515,7 @@ export var getTypeCastValue = function(variableValue, variableType, logger) {
512515/**
513516 * Returns an object containing all audiences in the project config. Keys are audience IDs
514517 * and values are audience objects.
515- * @param projectConfig
518+ * @param { Object } projectConfig
516519 * @returns {Object }
517520 */
518521export var getAudiencesById = function ( projectConfig ) {
@@ -521,44 +524,83 @@ export var getAudiencesById = function(projectConfig) {
521524
522525/**
523526 * Returns true if an event with the given key exists in the datafile, and false otherwise
524- * @param {Object } projectConfig
525- * @param {string } eventKey
527+ * @param {Object } projectConfig
528+ * @param {string } eventKey
526529 * @returns {boolean }
527530 */
528531export var eventWithKeyExists = function ( projectConfig , eventKey ) {
529532 return projectConfig . eventKeyMap . hasOwnProperty ( eventKey ) ;
530533} ;
531534
532535/**
533- *
536+ * Returns true if experiment belongs to any feature, false otherwise.
534537 * @param {Object } projectConfig
535538 * @param {string } experimentId
536- * @returns {boolean } Returns true if experiment belongs to
537- * any feature, false otherwise.
539+ * @returns {boolean }
538540 */
539541export var isFeatureExperiment = function ( projectConfig , experimentId ) {
540542 return projectConfig . experimentFeatureMap . hasOwnProperty ( experimentId ) ;
541543} ;
542544
545+ /**
546+ * Returns the JSON string representation of the datafile
547+ * @param {Object } projectConfig
548+ * @returns {string }
549+ */
550+ export var toDatafile = function ( projectConfig ) {
551+ return projectConfig . __datafileStr ;
552+ }
553+
554+ /**
555+ * @typedef {Object } TryCreatingProjectConfigResult
556+ * @property {Object|null } configObj
557+ * @property {Error|null } error
558+ */
559+
543560/**
544561 * Try to create a project config object from the given datafile and
545562 * configuration properties.
546- * If successful, return the project config object, otherwise throws an error
547- * @param {Object } config
548- * @param {Object } config.datafile
549- * @param {Object } config.jsonSchemaValidator
550- * @param {Object } config.logger
551- * @return {Object } Project config object
563+ * Returns an object with configObj and error properties.
564+ * If successful, configObj is the project config object, and error is null.
565+ * Otherwise, configObj is null and error is an error with more information.
566+ * @param {Object } config
567+ * @param {Object|string } config.datafile
568+ * @param {Object } config.jsonSchemaValidator
569+ * @param {Object } config.logger
570+ * @returns {TryCreatingProjectConfigResult }
552571 */
553572export var tryCreatingProjectConfig = function ( config ) {
554- configValidator . validateDatafile ( config . datafile ) ;
555- if ( ! config . jsonSchemaValidator ) {
556- config . logger . log ( LOG_LEVEL . INFO , sprintf ( LOG_MESSAGES . SKIPPING_JSON_VALIDATION , MODULE_NAME ) ) ;
573+
574+ var newDatafileObj ;
575+ try {
576+ newDatafileObj = configValidator . validateDatafile ( config . datafile ) ;
577+ } catch ( error ) {
578+ return { configObj : null , error } ;
579+ }
580+
581+ if ( config . jsonSchemaValidator ) {
582+ try {
583+ config . jsonSchemaValidator . validate ( newDatafileObj ) ;
584+ config . logger . log ( LOG_LEVEL . INFO , sprintf ( LOG_MESSAGES . VALID_DATAFILE , MODULE_NAME ) ) ;
585+ } catch ( error ) {
586+ return { configObj : null , error } ;
587+ }
557588 } else {
558- config . jsonSchemaValidator . validate ( config . datafile ) ;
559- config . logger . log ( LOG_LEVEL . INFO , sprintf ( LOG_MESSAGES . VALID_DATAFILE , MODULE_NAME ) ) ;
589+ config . logger . log ( LOG_LEVEL . INFO , sprintf ( LOG_MESSAGES . SKIPPING_JSON_VALIDATION , MODULE_NAME ) ) ;
590+ }
591+
592+ var createProjectConfigArgs = [ newDatafileObj ] ;
593+ if ( typeof config . datafile === 'string' ) {
594+ // Since config.datafile was validated above, we know that it is a valid JSON string
595+ createProjectConfigArgs . push ( config . datafile ) ;
560596 }
561- return this . createProjectConfig ( config . datafile ) ;
597+
598+ var newConfigObj = createProjectConfig ( ...createProjectConfigArgs ) ;
599+
600+ return {
601+ configObj : newConfigObj ,
602+ error : null ,
603+ } ;
562604} ;
563605
564606export default {
@@ -583,5 +625,6 @@ export default {
583625 getAudiencesById : getAudiencesById ,
584626 eventWithKeyExists : eventWithKeyExists ,
585627 isFeatureExperiment : isFeatureExperiment ,
628+ toDatafile : toDatafile ,
586629 tryCreatingProjectConfig : tryCreatingProjectConfig ,
587630} ;
0 commit comments