Manual Reference Source Test

src/modules/identity-config.js

import IdentityProperty from './identity-property';
import IdentityUser from './identity-user';

/**
 * Identity SDK configuration
 *
 * The way the properties map works is that you specify any IdentityProperty overrides for
 * standard properties or a complete IdentityProperty configuration for custom properties.
 *
 * For a list of standard properties see: {@link IdentityProperty.standardMap}.
 *
 * @property {string[]} redirectUrls - White list of redirect URLs to accept
 * @property {Map<string, IdentityProperty>} properties - Map of user property keys to configurations
 * @property {Map<string, string>} [facebook={}] - Facebook config
 * @property {Map<string, string>} [google={}] - Google config
 * @property {number} sessionTimeout - Session token timeout in seconds, default 1 year
 * @property {number} userTimeout - User data cache timeout in seconds, default 1 hour
 */
class IdentityConfig {
  /**
   * Returns Promise of IdentityConfig from specified server and with specified App key
   *
   * For each NBC App an IdentityConfig should be stored at: https://id.nbc.com/sdk/config/<key>.json
   * Where <key> is the App key, e.g: example => https://id.nbc.com/sdk/config/example.json
   *
   * For non production environments this URL will change accordingly, e.g. for dev:
   * https://dev-id.nbc.com/sdk/config/example.json
   *
   * @example
   * {
   *   "redirectUrls": [
   *     "https://id.nbc.com/sdk/example/"
   *   ],
   *   "properties": {
   *     "email": {}, // allow this credential to be used
   *     "firstName": { // extend config to request and require this whenever a user authenticates
   *       "request": true,
   *       "required": true
   *     },
   *     "lastName": { // request (but not require) this whenever a user authenticates
   *       "request": true
   *     },
   *     "sponsorOptIn": { // specify a complete configuration for custom properties (e.g: prefixed by app key)
   *       "label": "I want to get cool stuff from Sponsor",
   *       "type": "boolean",
   *       "required": true,
   *       "default_value": true
   *     }
   *   },
   *   "facebook": {
   *     "appId": "1234", // use a non standard Facebook App
   *     "permissions": ["email", "user_friends"] // besides the usual email, also ask for friends
   *   }
   * }
   *
   * @param {IdentityServer} [options.server] - IdentityServer to get config from
   * @param {String} [options.key] - Key of App to get configuration for
   * @param {String} [options.configLocationHost] - Custom config host url
   * @return {Promise<IdentityConfig, Error>} - Promise of IdentityConfig
   */
  static request({
    server,
    key,
    configLocationHost,
  }) {
    const replaceConfigLocation = configLocationHost ? configLocationHost.replace(/\/?$/, '/') : null;
    return server.sdk(`${!replaceConfigLocation ? 'config/' : ''}${key}.json`, replaceConfigLocation).then(
      (response) => new IdentityConfig(response),
      (error) => {
        // Fallback to nbc hosted config
        if (configLocationHost) {
          window.console.error('configLocationHost property error, falling back to nbc.com hosted config:', error);
          return this.request({server, key});
        }
      },
    );
  }

  /**
   * IdentityConfig constructor
   *
   * @param {string} [defaultPage='signUp'] - The default page to load on init
   * @param {string[]} [redirectUrls=[]] - White list of redirect URLs to accept
   * @param {Map<string, Object>} [properties={}] - Map of user property keys to configurations
   * @param {Map<string, string>} [facebook={}] - Facebook config
   * @param {Map<string, string>} [google={}] - Google config
   * @param {number} [sessionTimeout=31536000] - Session token timeout in seconds, default 1 year
   * @param {number} [userTimeout=3600] - User data cache timeout in seconds, default 1 hour
   * @param {Object} [theme={}] - Customizable theme parameters
   * @param {Object} [analytics={}] - Analytics settings
   * @param {Object} [zeroBounce={}] - ZeroBounce settings
   */
  constructor({
    defaultPage = 'signUp',
    redirectUrls = [],
    redirectDelay = 1000,
    redirectTimeout = 5000,
    logoutRedirectTimeout = 5000,
    properties = {},
    apple = {},
    facebook = {},
    google = {},
    peacock = {},
    sessionTimeout = 31536000,
    userTimeout = 3600,
    disableSmartLock = false,
    theme = {},
    analytics = {},
    showAttributes = {},
    launchdarkly = {},
    zeroBounce = {},
  }) {
    // Validate property config Objects and convert them to IdentityProperty instances
    const {credentialKeys} = IdentityProperty;
    const {serverKeyMap} = IdentityUser;
    const sdkKeys = Object.keys(serverKeyMap);
    const serverKeys = Object.values(serverKeyMap);

    // Ensure id and revisionId exist in the properties
    if (!properties.id) properties.id = {};
    if (!properties.revisionId) properties.revisionId = {};

    // Ensure Facebook config defaults exist
    if (!facebook.appId) facebook.appId = '1692464401052790';
    if (!facebook.permissions) facebook.permissions = ['public_profile', 'email'];
    if (!facebook.version) facebook.version = 'v3.1';

    Object.entries(properties).forEach(([key, property = {}]) => {
      if (credentialKeys.includes(key)) {
        if (Object.keys(property).length > 0) {
          throw new Error(`Credential properties can not be configured in IdentityConfig`);
        }
      }

      const serverKeyIndex = serverKeys.indexOf(key);
      if (serverKeyIndex >= 0) {
        throw new Error(`Illegal property key in IdentityConfig: "${key}", use "${sdkKeys[serverKeyIndex]}" instead`);
      }

      properties[key] = new IdentityProperty({
        ...IdentityProperty.standardMap[key], // use standard property as base (if any)
        ...property, // extend with property config
      });
    });

    Object.assign(this, {
      defaultPage,
      redirectUrls,
      redirectDelay,
      redirectTimeout,
      logoutRedirectTimeout,
      properties,
      apple,
      facebook,
      google,
      peacock,
      sessionTimeout,
      userTimeout,
      disableSmartLock,
      theme,
      analytics,
      showAttributes,
      launchdarkly,
      zeroBounce,
    });

    // Disable property modification
    Object.freeze(this);
  }
}

export default IdentityConfig;