addView (viewName, view) {
    if (view.includes('require:')) {
      let match = view.match(/require:([^;]+)/);
      const req = match[1];

      match = view.match(/title:([^;]+)/);
      if (!match) {
        console.log(`ERROR - ${viewName} view is missing 'title:' ${view}`);
        return;
      }
      const title = match[1];

      match = view.match(/fields:([^;]+)/);
      if (!match) {
        console.log(`ERROR - ${viewName} view is missing 'fields:' ${view}`);
        return;
      }
      const fields = match[1];

      // Can override the name in the view
      match = view.match(/section:([^;]+)/);
      if (match) {
        viewName = match[1];
      }

      const parts = req.split('.');
      let output = 'if (';
      for (let i = 0; i < parts.length; i++) {
        if (i > 0) {
          output += ' && ';
        }
        output += 'session';
        for (let j = 0; j <= i; j++) {
          output += `.${parts[j]}`;
        }
      }
      output += ')\n';
      output += `  div.sessionDetailMeta.bold ${title}\n  dl.sessionDetailMeta\n`;

      for (const field of fields.split(',')) {
        const info = WISESource.field2Info.get(field);
        if (!info) {
          continue;
        }
        if (!info.db) {
          console.log(`ERROR - missing db information for ${field}`);
          return;
        }
        const pos = info.db.lastIndexOf('.');
        if (pos === -1) {
          output += `    +arrayList(session, '${info.db}', '${info.friendly}', '${field}')\n`;
        } else {
          output += `    +arrayList(session.${info.db.slice(0, pos)}, '${info.db.slice(pos + 1)}', '${info.friendly}', '${field}')\n`;
        }
      }

      internals.views.set(viewName, output);
    } else {
      internals.views.set(viewName, view);
    }
  }
Add a view

@param {string} viewName - Name of the new view
@param {string} view - An encoded view definition