github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/app/serializers/application.js (about)

     1  import { copy } from 'ember-copy';
     2  import { get } from '@ember/object';
     3  import { makeArray } from '@ember/array';
     4  import JSONSerializer from '@ember-data/serializer/json';
     5  import { pluralize, singularize } from 'ember-inflector';
     6  import removeRecord from '../utils/remove-record';
     7  import { assign } from '@ember/polyfills';
     8  
     9  export default class Application extends JSONSerializer {
    10    primaryKey = 'ID';
    11  
    12    /**
    13      A list of keys that are converted to empty arrays if their value is null.
    14  
    15      arrayNullOverrides = ['Array'];
    16      { Array: null } => { Array: [] }
    17  
    18      @property arrayNullOverrides
    19      @type String[]
    20     */
    21    arrayNullOverrides = null;
    22  
    23    /**
    24      A list of keys that are converted to empty objects if their value is null.
    25  
    26      objectNullOverrides = ['Object'];
    27      { Object: null } => { Object: {} }
    28  
    29      @property objectNullOverrides
    30      @type String[]
    31     */
    32    objectNullOverrides = null;
    33  
    34    /**
    35      A list of keys or objects to convert a map into an array of maps with the original map keys as Name properties.
    36  
    37      mapToArray = ['Map'];
    38      { Map: { a: { x: 1 } } } => { Map: [ { Name: 'a', x: 1 }] }
    39  
    40      mapToArray = [{ beforeName: 'M', afterName: 'Map' }];
    41      { M: { a: { x: 1 } } } => { Map: [ { Name: 'a', x: 1 }] }
    42  
    43      @property mapToArray
    44      @type (String|Object)[]
    45     */
    46    mapToArray = null;
    47  
    48    /**
    49      A list of keys for nanosecond timestamps that will be split into two properties: `separateNanos = ['Time']` will
    50      produce a `Time` property with a millisecond timestamp and `TimeNanos` with the nanoseconds alone.
    51  
    52      separateNanos = ['Time'];
    53      { Time: 1607839992000100000 } => { Time: 1607839992000, TimeNanos: 100096 }
    54  
    55      @property separateNanos
    56      @type String[]
    57     */
    58    separateNanos = null;
    59  
    60    keyForAttribute(attr) {
    61      return attr.camelize().capitalize();
    62    }
    63  
    64    keyForRelationship(attr, relationshipType) {
    65      const key = `${singularize(attr)
    66        .camelize()
    67        .capitalize()}ID`;
    68      return relationshipType === 'hasMany' ? pluralize(key) : key;
    69    }
    70  
    71    // Modeled after the pushPayload for ember-data/serializers/rest
    72    pushPayload(store, payload) {
    73      const documentHash = {
    74        data: [],
    75        included: [],
    76      };
    77  
    78      Object.keys(payload).forEach(key => {
    79        const modelName = this.modelNameFromPayloadKey(key);
    80        const serializer = store.serializerFor(modelName);
    81        const type = store.modelFor(modelName);
    82  
    83        makeArray(payload[key]).forEach(hash => {
    84          const { data, included } = serializer.normalize(type, hash, key);
    85          documentHash.data.push(data);
    86          if (included) {
    87            documentHash.included.push(...included);
    88          }
    89        });
    90      });
    91  
    92      store.push(documentHash);
    93    }
    94  
    95    normalize(modelClass, hash) {
    96      if (hash) {
    97        if (this.arrayNullOverrides) {
    98          this.arrayNullOverrides.forEach(key => {
    99            if (!hash[key]) {
   100              hash[key] = [];
   101            }
   102          });
   103        }
   104        if (this.objectNullOverrides) {
   105          this.objectNullOverrides.forEach(key => {
   106            if (!hash[key]) {
   107              hash[key] = {};
   108            }
   109          });
   110        }
   111  
   112        if (this.mapToArray) {
   113          this.mapToArray.forEach(conversion => {
   114            let apiKey, uiKey;
   115  
   116            if (conversion.beforeName) {
   117              apiKey = conversion.beforeName;
   118              uiKey = conversion.afterName;
   119            } else {
   120              apiKey = conversion;
   121              uiKey = conversion;
   122            }
   123  
   124            const map = hash[apiKey] || {};
   125  
   126            hash[uiKey] = Object.keys(map)
   127              .sort()
   128              .map(mapKey => {
   129                const propertiesForKey = map[mapKey] || {};
   130                const convertedMap = { Name: mapKey };
   131  
   132                assign(convertedMap, propertiesForKey);
   133  
   134                return convertedMap;
   135              });
   136          });
   137        }
   138  
   139        if (this.separateNanos) {
   140          this.separateNanos.forEach(key => {
   141            const timeWithNanos = hash[key];
   142            hash[`${key}Nanos`] = timeWithNanos % 1000000;
   143            hash[key] = Math.floor(timeWithNanos / 1000000);
   144          });
   145        }
   146      }
   147  
   148      return super.normalize(modelClass, hash);
   149    }
   150  
   151    normalizeFindAllResponse(store, modelClass) {
   152      const result = super.normalizeFindAllResponse(...arguments);
   153      this.cullStore(store, modelClass.modelName, result.data);
   154      return result;
   155    }
   156  
   157    // When records are removed server-side, and therefore don't show up in requests,
   158    // the local copies of those records need to be unloaded from the store.
   159    cullStore(store, type, records, storeFilter = () => true) {
   160      const newRecords = copy(records).filter(record => get(record, 'id'));
   161      const oldRecords = store.peekAll(type);
   162      oldRecords
   163        .filter(record => get(record, 'id'))
   164        .filter(storeFilter)
   165        .forEach(old => {
   166          const newRecord = newRecords.find(record => get(record, 'id') === get(old, 'id'));
   167          if (!newRecord) {
   168            removeRecord(store, old);
   169          } else {
   170            newRecords.removeObject(newRecord);
   171          }
   172        });
   173    }
   174  
   175    modelNameFromPayloadKey(key) {
   176      return singularize(key.dasherize());
   177    }
   178  }