All files NetworkStore.ts

100% Statements 48/48
100% Branches 34/34
100% Functions 15/15
100% Lines 42/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 1151x             1x 1x   1x                                   1x                   62x 61x       61x 61x     61x             61x 61x     1x 61x     1x 61x     1x 61x     1x 61x   61x 5x     61x     1x 61x 3x 2x   1x       1x 63x     1x 61x 10x   61x     123x 62x   62x 4x 1x   3x       62x   1x  
import {Collection, IModelConstructor} from 'mobx-collection-store';
 
import IDictionary from './interfaces/IDictionary';
import IFilters from './interfaces/IFilters';
import IHeaders from './interfaces/IHeaders';
import IRequestOptions from './interfaces/IRequestOptions';
import * as JsonApi from './interfaces/JsonApi';
import {config} from './NetworkUtils';
import {getValue, objectForEach} from './utils';
 
export class NetworkStore extends Collection {
 
  /**
   * Prepare the query params for the API call
   *
   * @protected
   * @param {string} type Record type
   * @param {(number|string)} [id] Record ID
   * @param {JsonApi.IRequest} [data] Request data
   * @param {IRequestOptions} [options] Server options
   * @returns {{
   *     url: string,
   *     data?: object,
   *     headers: IHeaders,
   *   }} Options needed for an API call
   *
   * @memberOf NetworkStore
   */
  protected __prepareQuery(
    type: string,
    id?: number|string,
    data?: JsonApi.IRequest,
    options?: IRequestOptions,
  ): {
    url: string,
    data?: object,
    headers: IHeaders,
  } {
    const model: IModelConstructor = this.static.types.filter((item) => item.type === type)[0];
    const path: string = model
      ? (getValue<string>(model['endpoint']) || model['baseUrl'] || model.type)
      : type;
 
    const url: string = id ? `${path}/${id}` : `${path}`;
    const headers: IDictionary<string> = options ? options.headers : {};
 
    const params: Array<string> = [
      ...this.__prepareFilters((options && options.filter) || {}),
      ...this.__prepareSort(options && options.sort),
      ...this.__prepareIncludes(options && options.include),
      ...this.__prepareFields((options && options.fields) || {}),
      ...this.__prepareRawParams((options && options.params) || []),
    ];
 
    const baseUrl: string = this.__appendParams(this.__prefixUrl(url), params);
    return {data, headers, url: baseUrl};
  }
 
  protected __prepareFilters(filters: IFilters): Array<string> {
    return this.__parametrize(filters).map((item) => `filter[${item.key}]=${item.value}`);
  }
 
  protected __prepareSort(sort?: string|Array<string>): Array<string> {
    return sort ? [`sort=${sort}`] : [];
  }
 
  protected __prepareIncludes(include?: string|Array<string>): Array<string> {
    return include ? [`include=${include}`] : [];
  }
 
  protected __prepareFields(fields: IDictionary<string|Array<string>>): Array<string> {
    const list = [];
 
    objectForEach(fields, (key: string) => {
      list.push(`fields[${key}]=${fields[key]}`);
    });
 
    return list;
  }
 
  protected __prepareRawParams(params: Array<{key: string, value: string}|string>): Array<string> {
    return params.map((param) => {
      if (typeof param === 'string') {
        return param;
      }
      return `${param.key}=${param.value}`;
    });
  }
 
  protected __prefixUrl(url) {
    return `${config.baseUrl}${url}`;
  }
 
  protected __appendParams(url: string, params: Array<string>): string {
    if (params.length) {
      url += '?' + params.join('&');
    }
    return url;
  }
 
  private __parametrize(params: object, scope: string = ''): Array<{key: string, value: string}> {
    const list = [];
 
    objectForEach(params, (key: string) => {
      if (typeof params[key] === 'object') {
        list.push(...this.__parametrize(params[key], `${key}.`));
      } else {
        list.push({key: `${scope}${key}`, value: params[key]});
      }
    });
 
    return list;
  }
}