code: function getFormViewModel(formName, config, callback) {
    var cacheTtl = config.cacheOptions && config.cacheOptions.ttl !== undefined ? config.cacheOptions.ttl : config.client.cacheManager.defaultTtl;
    var cachedModel = cache.getCachedItem(formName, cacheTtl);
  
    if (cachedModel) {
      return process.nextTick(function () {
        callback(null, _.cloneDeep(cachedModel));
      });
    }
  
    var form = config.web[formName].form;
    var fields = getFormFields(form);
  
    var model = {
      form: {
        fields: fields
      },
      accountStores: null
    };
  
    // TODO fetch identity providers from Okta so that we can build a list of
    // social login buttons
  
    model.accountStores = [];
  
    cache.setCachedItem(formName, model);
  
    callback(null, _.cloneDeep(model));
  
  }
docs: Returns an object containing:
  
  - A list of all enabled fields, as defined by `form.fields`,
  and ordered by `form.fieldOrder`.
  - A list of providers, such as social providers or SAML providers.
  
  <https://github.com/stormpath/stormpath-framework-spec/blob/master/login.md#login-view-model>
  <https://github.com/stormpath/stormpath-framework-spec/blob/master/registration.md#registration-view-model>
  
  @method
  
  @param {string} formName - The name of the form (e.g. 'login' or 'register').
  @param {Object} config - The Stormpath configuration.
  @param {Function} callback - Callback function (error, model).