open-nomad/ui/app/adapters/application.js

129 lines
3.3 KiB
JavaScript

import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import RESTAdapter from '@ember-data/adapter/rest';
import codesForError from '../utils/codes-for-error';
import removeRecord from '../utils/remove-record';
import { default as NoLeaderError, NO_LEADER } from '../utils/no-leader-error';
import classic from 'ember-classic-decorator';
export const namespace = 'v1';
@classic
export default class ApplicationAdapter extends RESTAdapter {
namespace = namespace;
@service system;
@service token;
@computed('token.secret')
get headers() {
const token = this.get('token.secret');
if (token) {
return {
'X-Nomad-Token': token,
};
}
return undefined;
}
handleResponse(status, headers, payload) {
if (status === 500 && payload === NO_LEADER) {
return new NoLeaderError();
}
return super.handleResponse(...arguments);
}
findAll() {
return super.findAll(...arguments).catch((error) => {
const errorCodes = codesForError(error);
const isNotImplemented = errorCodes.includes('501');
if (isNotImplemented) {
return [];
}
// Rethrow to be handled downstream
throw error;
});
}
ajaxOptions(url, verb, options = {}) {
options.data || (options.data = {});
if (this.get('system.shouldIncludeRegion')) {
// Region should only ever be a query param. The default ajaxOptions
// behavior is to include data attributes in the requestBody for PUT
// and POST requests. This works around that.
const region = this.get('system.activeRegion');
if (region) {
url = associateRegion(url, region);
}
}
return super.ajaxOptions(url, verb, options);
}
// In order to remove stale records from the store, findHasMany has to unload
// all records related to the request in question.
findHasMany(store, snapshot, link, relationship) {
return super.findHasMany(...arguments).then((payload) => {
const relationshipType = relationship.type;
const inverse = snapshot.record.inverseFor(relationship.key);
if (inverse) {
store
.peekAll(relationshipType)
.filter((record) => record.get(`${inverse.name}.id`) === snapshot.id)
.forEach((record) => {
removeRecord(store, record);
});
}
return payload;
});
}
// Single record requests deviate from REST practice by using
// the singular form of the resource name.
//
// REST: /some-resources/:id
// Nomad: /some-resource/:id
//
// This is the original implementation of _buildURL
// without the pluralization of modelName
urlForFindRecord(id, modelName) {
let path;
let url = [];
let host = this.host;
let prefix = this.urlPrefix();
if (modelName) {
path = modelName.camelize();
if (path) {
url.push(path);
}
}
if (id) {
url.push(encodeURIComponent(id));
}
if (prefix) {
url.unshift(prefix);
}
url = url.join('/');
if (!host && url && url.charAt(0) !== '/') {
url = '/' + url;
}
return url;
}
urlForUpdateRecord() {
return this.urlForFindRecord(...arguments);
}
}
function associateRegion(url, region) {
return url.indexOf('?') !== -1 ? `${url}&region=${region}` : `${url}?region=${region}`;
}