<commit_before>import { List as IList, Map as IMap } from 'immutable';
import { widgetsConstants } from 'molecular-design-applications-shared';
import axios from 'axios';
import AppRecord from '../records/app_record';
import PipeRecord from '../records/pipe_record';
import PipeDataRecord from '../records/pipe_data_record';
import RunRecord from '../records/run_record';
import WidgetRecord from '../records/widget_record';
import pipeUtils from './pipe_utils';

const API_URL = process.env.API_URL || '';

const apiUtils = {
  /**
   * Fetch all apps
   * @returns {Promise}
   */
  getApps() {
    return axios.get(`${API_URL}/v1/app`)
      .then(res =>
        res.data.map(appData => new AppRecord(appData)),
      );
  },

  /**
   * Fetch an app from the server (when there is no run)
   * @param {String} appId
   * @returns {Promise resolves with AppRecord}
   */
  getApp(appId) {
    return axios.get(`${API_URL}/v1/app/${appId}`)
      .then((res) => {
        let widgets = new IList(
          res.data.widgets.map((widgetData) => {
            let inputPipes = widgetData.inputs ?
              new IList(widgetData.inputs.map(
                inputPipeJson => new PipeRecord({
                  name: inputPipeJson.id,
                  sourceWidgetId: inputPipeJson.source,
                }),
              )) : new IList();
            const outputPipes = widgetData.outputs ?
              new IList(widgetData.outputs.map(
                outputPipeJson => new PipeRecord({
                  name: outputPipeJson.id,
                  sourceWidgetId: widgetData.id,
                }),
              )) : new IList();

            // Hack in email requirement (TODO remove with auth)
            inputPipes = inputPipes.push(new PipeRecord({
              name: 'email',
              sourceWidgetId: widgetsConstants.ENTER_EMAIL,
            }));

            return new WidgetRecord(
              Object.assign({}, widgetData, { inputPipes, outputPipes }),
            );
          }),
        );

        // Hack in email widget (TODO remove with Auth)
        widgets = widgets.unshift(new WidgetRecord({
          id: widgetsConstants.ENTER_EMAIL,
          title: 'Enter Email',
          outputPipes: new IList([
            new PipeRecord({
              name: 'email',
              sourceWidgetId: widgetsConstants.ENTER_EMAIL,
            }),
          ]),
        }));

        return new AppRecord(Object.assign({}, res.data, {
          widgets,
          run: new RunRecord(),
        }));
      });
  },

  /**
   * Get the indicated run data from the server
   * @param {String} runId
   * @returns {Promise resolves with RunRecord}
   */
  getRun(runId) {
    return axios.get(`${API_URL}/v1/session/${runId}`)
      .then(res =>
        res.data,
      )
      .then((runData) => {
        let pipeDatasByWidget = new IMap();

        Object.entries(runData.widgets).forEach(([widgetId, widgetData]) => {
          let pipeDatas = new IList();
          const widgetPipeDatas = Object.entries(widgetData.in)
            .concat(Object.entries(widgetData.out));

          widgetPipeDatas.forEach(([pipeName, pipeDataServer]) => {
            pipeDatas = pipeDatas.push(
              new PipeDataRecord(Object.assign({}, pipeDataServer, {
                pipeName,
                widgetId,
              })),
            );
          });

          pipeDatasByWidget = pipeDatasByWidget.set(widgetId, pipeDatas);
        });

        return new RunRecord(Object.assign({}, runData, {
          id: runId,
          pipeDatasByWidget,
        }));
      });
  },
<commit_msg>Fix bug where initial step with no inputs causes error so page doesnt load<commit_after>import { List as IList, Map as IMap } from 'immutable';
import { widgetsConstants } from 'molecular-design-applications-shared';
import axios from 'axios';
import AppRecord from '../records/app_record';
import PipeRecord from '../records/pipe_record';
import PipeDataRecord from '../records/pipe_data_record';
import RunRecord from '../records/run_record';
import WidgetRecord from '../records/widget_record';
import pipeUtils from './pipe_utils';

const API_URL = process.env.API_URL || '';

const apiUtils = {
  /**
   * Fetch all apps
   * @returns {Promise}
   */
  getApps() {
    return axios.get(`${API_URL}/v1/app`)
      .then(res =>
        res.data.map(appData => new AppRecord(appData)),
      );
  },

  /**
   * Fetch an app from the server (when there is no run)
   * @param {String} appId
   * @returns {Promise resolves with AppRecord}
   */
  getApp(appId) {
    return axios.get(`${API_URL}/v1/app/${appId}`)
      .then((res) => {
        let widgets = new IList(
          res.data.widgets.map((widgetData) => {
            let inputPipes = widgetData.inputs ?
              new IList(widgetData.inputs.map(
                inputPipeJson => new PipeRecord({
                  name: inputPipeJson.id,
                  sourceWidgetId: inputPipeJson.source,
                }),
              )) : new IList();
            const outputPipes = widgetData.outputs ?
              new IList(widgetData.outputs.map(
                outputPipeJson => new PipeRecord({
                  name: outputPipeJson.id,
                  sourceWidgetId: widgetData.id,
                }),
              )) : new IList();

            // Hack in email requirement (TODO remove with auth)
            inputPipes = inputPipes.push(new PipeRecord({
              name: 'email',
              sourceWidgetId: widgetsConstants.ENTER_EMAIL,
            }));

            return new WidgetRecord(
              Object.assign({}, widgetData, { inputPipes, outputPipes }),
            );
          }),
        );

        // Hack in email widget (TODO remove with Auth)
        widgets = widgets.unshift(new WidgetRecord({
          id: widgetsConstants.ENTER_EMAIL,
          title: 'Enter Email',
          outputPipes: new IList([
            new PipeRecord({
              name: 'email',
              sourceWidgetId: widgetsConstants.ENTER_EMAIL,
            }),
          ]),
        }));

        return new AppRecord(Object.assign({}, res.data, {
          widgets,
          run: new RunRecord(),
        }));
      });
  },

  /**
   * Get the indicated run data from the server
   * @param {String} runId
   * @returns {Promise resolves with RunRecord}
   */
  getRun(runId) {
    return axios.get(`${API_URL}/v1/session/${runId}`)
      .then(res =>
        res.data,
      )
      .then((runData) => {
        let pipeDatasByWidget = new IMap();

        Object.entries(runData.widgets).forEach(([widgetId, widgetData]) => {
          let pipeDatas = new IList();
          const widgetPipeDatas = Object.entries(widgetData.in || {})
            .concat(Object.entries(widgetData.out || {}));

          widgetPipeDatas.forEach(([pipeName, pipeDataServer]) => {
            pipeDatas = pipeDatas.push(
              new PipeDataRecord(Object.assign({}, pipeDataServer, {
                pipeName,
                widgetId,
              })),
            );
          });

          pipeDatasByWidget = pipeDatasByWidget.set(widgetId, pipeDatas);
        });

        return new RunRecord(Object.assign({}, runData, {
          id: runId,
          pipeDatasByWidget,
        }));
      });
  },

{'fraction_non_alphanumeric': 0.12535924456001094, 'fraction_numerical': 0.0008211304228821678, 'mean_word_length': 1.9023034154090548, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7230384', 'n_tokens_mistral': 2112, 'n_tokens_neox': 2076, 'n_words': 461}