mirror of
https://github.com/status-im/consul.git
synced 2025-01-10 13:55:55 +00:00
27c74f7141
* Model layer changes to turn Node:ServiceInstances into hasMany We tried to make something that feels a little like ember-data yet not leave our approach of re-shaping the JSON directly from the response. 1. We added transformHasManyResponse for re-shaping JSON for hasMany relationships. we avoided the normalize word as ember-data serialize methods usually return something JSON:API shaped and we distinctly don't want to do that. Transform was the best word we could think of. 2. The integration tests across all of our models here feel very much like those types of tests that aren't really testing much, or assert too much to an extent that they get in the way rather than be of any use. I'd very much like to move a lot of this to unit tests. Currently most of the fingerprinting functionality is unit tested and these integration tests were originally to give confidence that IDs and related properties were being added correctly. 3. We've added a hasMany relationship, but not the corresponding belongsTo - yet at least. We don't require the belongsTo right now, and if we do we can add it later. * Integrate ServiceInstance search bar for Node:ServiceInstances * Hide Node.Meta when on the Node:ServiceINstance page We use a little string replace hack here for a human-like label, this is soon to be replaced with proper i10n replacement * Always ensure that a Namespace is set, and add comment explaining
163 lines
4.7 KiB
JavaScript
163 lines
4.7 KiB
JavaScript
import { inject as service } from '@ember/service';
|
|
import Adapter from '@ember-data/adapter';
|
|
import AdapterError, {
|
|
AbortError,
|
|
TimeoutError,
|
|
ServerError,
|
|
UnauthorizedError,
|
|
ForbiddenError,
|
|
NotFoundError,
|
|
ConflictError,
|
|
InvalidError,
|
|
} from '@ember-data/adapter/error';
|
|
|
|
// TODO These are now exactly the same, apart from the fact that one uses
|
|
// `serialized, unserialized` and the other just `query`
|
|
// they could actually be one function now, but would be nice to think about
|
|
// the naming of things (serialized vs query etc)
|
|
const read = function(adapter, modelName, type, query = {}) {
|
|
return adapter.rpc(
|
|
function(adapter, ...rest) {
|
|
return adapter[`requestFor${type}`](...rest);
|
|
},
|
|
function(serializer, ...rest) {
|
|
return serializer[`respondFor${type}`](...rest);
|
|
},
|
|
query,
|
|
modelName
|
|
);
|
|
};
|
|
const write = function(adapter, modelName, type, snapshot) {
|
|
return adapter.rpc(
|
|
function(adapter, ...rest) {
|
|
return adapter[`requestFor${type}`](...rest);
|
|
},
|
|
function(serializer, ...rest) {
|
|
return serializer[`respondFor${type}`](...rest);
|
|
},
|
|
snapshot,
|
|
modelName
|
|
);
|
|
};
|
|
export default class HttpAdapter extends Adapter {
|
|
@service('client/http') client;
|
|
|
|
rpc(req, resp, obj, modelName) {
|
|
const client = this.client;
|
|
const store = this.store;
|
|
const adapter = this;
|
|
|
|
let unserialized, serialized;
|
|
const serializer = store.serializerFor(modelName);
|
|
const modelClass = store.modelFor(modelName);
|
|
// workable way to decide whether this is a snapshot
|
|
// essentially 'is attributable'.
|
|
// Snapshot is private so we can't do instanceof here
|
|
// and using obj.constructor.name gets changed/minified
|
|
// during compilation so you can't rely on it
|
|
// checking for `attributes` being a function is more
|
|
// reliable as that is the thing we need to call
|
|
if (typeof obj.attributes === 'function') {
|
|
unserialized = obj.attributes();
|
|
serialized = serializer.serialize(obj, {});
|
|
} else {
|
|
unserialized = obj;
|
|
serialized = unserialized;
|
|
}
|
|
|
|
return client
|
|
.request(function(request) {
|
|
return req(adapter, request, serialized, unserialized, modelClass);
|
|
})
|
|
.catch(function(e) {
|
|
return adapter.error(e);
|
|
})
|
|
.then(function(respond) {
|
|
// TODO: When HTTPAdapter:responder changes, this will also need to change
|
|
return resp(serializer, respond, serialized, unserialized, modelClass);
|
|
});
|
|
// TODO: Potentially add specific serializer errors here
|
|
// .catch(function(e) {
|
|
// return Promise.reject(e);
|
|
// });
|
|
}
|
|
|
|
error(err) {
|
|
if (err instanceof TypeError) {
|
|
throw err;
|
|
}
|
|
const errors = [
|
|
{
|
|
status: `${err.statusCode}`,
|
|
title: 'The backend responded with an error',
|
|
detail: err.message,
|
|
},
|
|
];
|
|
let error;
|
|
const detailedMessage = '';
|
|
try {
|
|
switch (err.statusCode) {
|
|
case 0:
|
|
error = new AbortError();
|
|
error.errors[0].status = '0';
|
|
break;
|
|
case 401:
|
|
error = new UnauthorizedError(errors, detailedMessage);
|
|
break;
|
|
case 403:
|
|
error = new ForbiddenError(errors, detailedMessage);
|
|
break;
|
|
case 404:
|
|
error = new NotFoundError(errors, detailedMessage);
|
|
break;
|
|
case 408:
|
|
error = new TimeoutError();
|
|
break;
|
|
case 409:
|
|
error = new ConflictError(errors, detailedMessage);
|
|
break;
|
|
case 422:
|
|
error = new InvalidError(errors); //payload.errors
|
|
break;
|
|
default:
|
|
if (err.statusCode >= 500) {
|
|
error = new ServerError(errors, detailedMessage);
|
|
} else {
|
|
error = new AdapterError(errors, detailedMessage);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
// TODO: This comes originates from ember-data
|
|
// This can be confusing if you need to use this with Promise.reject
|
|
// Consider changing this to return the error and then
|
|
// throw from the call site instead
|
|
throw error;
|
|
}
|
|
|
|
query(store, type, query) {
|
|
return read(this, type.modelName, 'Query', query);
|
|
}
|
|
|
|
queryRecord(store, type, query) {
|
|
return read(this, type.modelName, 'QueryRecord', query);
|
|
}
|
|
|
|
findAll(store, type) {
|
|
return read(this, type.modelName, 'FindAll');
|
|
}
|
|
|
|
createRecord(store, type, snapshot) {
|
|
return write(this, type.modelName, 'CreateRecord', snapshot);
|
|
}
|
|
|
|
updateRecord(store, type, snapshot) {
|
|
return write(this, type.modelName, 'UpdateRecord', snapshot);
|
|
}
|
|
|
|
deleteRecord(store, type, snapshot) {
|
|
return write(this, type.modelName, 'DeleteRecord', snapshot);
|
|
}
|
|
}
|