open-consul/ui-v2/app/serializers/application.js

132 lines
4.2 KiB
JavaScript

import Serializer from './http';
import { set } from '@ember/object';
import {
HEADERS_SYMBOL as HTTP_HEADERS_SYMBOL,
HEADERS_INDEX as HTTP_HEADERS_INDEX,
} from 'consul-ui/utils/http/consul';
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
import createFingerprinter from 'consul-ui/utils/create-fingerprinter';
const map = function(obj, cb) {
if (!Array.isArray(obj)) {
return [obj].map(cb)[0];
}
return obj.map(cb);
};
const attachHeaders = function(headers, body) {
// lowercase everything incase we get browser inconsistencies
const lower = {};
Object.keys(headers).forEach(function(key) {
lower[key.toLowerCase()] = headers[key];
});
body[HTTP_HEADERS_SYMBOL] = lower;
return body;
};
export default Serializer.extend({
fingerprint: createFingerprinter(DATACENTER_KEY),
respondForQuery: function(respond, query) {
return respond((headers, body) =>
attachHeaders(headers, map(body, this.fingerprint(this.primaryKey, this.slugKey, query.dc)))
);
},
respondForQueryRecord: function(respond, query) {
return respond((headers, body) =>
attachHeaders(headers, this.fingerprint(this.primaryKey, this.slugKey, query.dc)(body))
);
},
respondForCreateRecord: function(respond, serialized, data) {
const slugKey = this.slugKey;
const primaryKey = this.primaryKey;
return respond((headers, body) => {
// If creates are true use the info we already have
if (body === true) {
body = data;
}
// Creates need a primaryKey adding
return this.fingerprint(primaryKey, slugKey, data[DATACENTER_KEY])(body);
});
},
respondForUpdateRecord: function(respond, serialized, data) {
const slugKey = this.slugKey;
const primaryKey = this.primaryKey;
return respond((headers, body) => {
// If updates are true use the info we already have
if (body === true) {
body = data;
}
return this.fingerprint(primaryKey, slugKey, data[DATACENTER_KEY])(body);
});
},
respondForDeleteRecord: function(respond, serialized, data) {
const slugKey = this.slugKey;
const primaryKey = this.primaryKey;
return respond((headers, body) => {
// Deletes only need the primaryKey/uid returning
return {
[primaryKey]: this.fingerprint(primaryKey, slugKey, data[DATACENTER_KEY])({
[slugKey]: data[slugKey],
})[primaryKey],
};
});
},
// this could get confusing if you tried to override
// say `normalizeQueryResponse`
// TODO: consider creating a method for each one of the `normalize...Response` family
normalizeResponse: function(store, primaryModelClass, payload, id, requestType) {
// Pick the meta/headers back off the payload and cleanup
// before we go through serializing
const headers = payload[HTTP_HEADERS_SYMBOL] || {};
delete payload[HTTP_HEADERS_SYMBOL];
const normalizedPayload = this.normalizePayload(payload, id, requestType);
// put the meta onto the response, here this is ok
// as JSON-API allows this and our specific data is now in
// response[primaryModelClass.modelName]
// so we aren't in danger of overwriting anything
// (which was the reason for the Symbol-like property earlier)
// use a method modelled on ember-data methods so we have the opportunity to
// do this on a per-model level
const meta = this.normalizeMeta(
store,
primaryModelClass,
headers,
normalizedPayload,
id,
requestType
);
if (requestType === 'queryRecord') {
normalizedPayload.meta = meta;
}
return this._super(
store,
primaryModelClass,
{
meta: meta,
[primaryModelClass.modelName]: normalizedPayload,
},
id,
requestType
);
},
timestamp: function() {
return new Date().getTime();
},
normalizeMeta: function(store, primaryModelClass, headers, payload, id, requestType) {
const meta = {
cursor: headers[HTTP_HEADERS_INDEX],
};
if (requestType === 'query') {
meta.date = this.timestamp();
payload.forEach(function(item) {
set(item, 'SyncTime', meta.date);
});
}
return meta;
},
normalizePayload: function(payload, id, requestType) {
return payload;
},
});