stubby
Version:
a lightweight server for stubbing external systems and endpoints
169 lines (139 loc) • 3.87 kB
JavaScript
;
const httpMethods = [
'GET',
'PUT',
'POST',
'HEAD',
'PATCH',
'TRACE',
'DELETE',
'CONNECT',
'OPTIONS'
];
const messages = {
json: 'An unparseable JSON string was supplied.',
request: {
missing: "'request' object is required.",
url: "'request.url' is required.",
query: {
type: "'request.query', if supplied, must be an object."
},
method: "'request.method' must be one of " + httpMethods + '.',
headers: {
type: "'request.headers', if supplied, must be an object."
}
},
response: {
headers: {
type: "'response.headers', if supplied, must be an object."
},
status: {
type: "'response.status' must be integer-like.",
small: "'response.status' must be >= 100.",
large: "'response.status' must be < 600."
},
latency: {
type: "'response.latency' must be integer-like."
}
}
};
const response = {
status: function (status) {
if (!status) { return null; }
const parsed = parseInt(status, 10);
if (!parsed) { return messages.response.status.type; }
if (parsed < 100) { return messages.response.status.small; }
if (parsed >= 600) { return messages.response.status.large; }
return null;
},
headers: function (headers) {
if (!headers) { return null; }
if (headers instanceof Array || typeof headers !== 'object') {
return messages.response.headers.type;
}
return null;
},
latency: function (latency) {
if (!latency) { return null; }
if (!parseInt(latency, 10)) { return messages.response.latency.type; }
return null;
}
};
const request = {
url: function (url) {
if (url) { return null; }
return messages.request.url;
},
headers: function (headers) {
if (!headers) { return null; }
if (headers instanceof Array || typeof headers !== 'object') {
return messages.request.headers.type;
}
return null;
},
method: function (method) {
let i;
if (!method) { return null; }
if (!(method instanceof Array)) {
if (httpMethods.indexOf(method.toUpperCase()) !== -1) {
return null;
}
return messages.request.method;
}
for (i = 0; i < method.length; i++) {
if (httpMethods.indexOf(method[i].toUpperCase()) === -1) {
return messages.request.method;
}
}
return null;
},
query: function (query) {
if (!query) { return null; }
if (query instanceof Array || typeof query !== 'object') {
return messages.request.query.type;
}
return null;
}
};
function contract (endpoint) {
let results, property;
let errors = [];
if (typeof endpoint === 'string') {
try {
endpoint = JSON.parse(endpoint);
} catch (e) {
return [messages.json];
}
}
if (endpoint instanceof Array) {
results = endpoint.map(function (it) { return contract(it); });
results = results.filter(function (result) { return result !== null; });
if (results.length === 0) { return null; }
return results;
}
if (!endpoint.request) {
errors.push(messages.request.missing);
} else {
for (property in request) {
if (Object.prototype.hasOwnProperty.call(request, property)) {
errors.push(request[property](endpoint.request[property]));
}
}
}
if (endpoint.response) {
if (!(endpoint.response instanceof Array)) {
endpoint.response = [endpoint.response];
}
endpoint.response.forEach(function (incoming) {
for (property in response) {
if (Object.prototype.hasOwnProperty.call(response, property)) {
errors.push(response[property](incoming[property]));
}
}
});
}
errors = errors.filter(function (error) { return error !== null; });
if (errors.length === 0) { errors = null; }
return errors;
}
module.exports = contract;