react-api-adts
Version:
Helpful algebraic data types for API handling in React apps.
125 lines (124 loc) • 4.45 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.API = exports.ackDecoder = exports.Decoder = exports.Encoder = void 0;
const axios_1 = require("axios");
const result_1 = require("./result");
class Encoder {
constructor(contentType, encode) {
this.contentType = contentType;
this.encode = encode;
}
}
exports.Encoder = Encoder;
class Decoder {
constructor(contentType, decode) {
this.contentType = contentType;
this.decode = decode;
}
map(fun) {
return new Decoder(this.contentType, (input) => fun(this.decode(input)));
}
}
exports.Decoder = Decoder;
function ackDecoder() {
return new Decoder("*/*", () => 0);
}
exports.ackDecoder = ackDecoder;
class API {
constructor(urlPrefix, validErrorDecoder, authErrorDecoder, timeoutMillis) {
this.urlPrefix = urlPrefix;
this.validErrorDecoder = validErrorDecoder;
this.authErrorDecoder = authErrorDecoder;
this.timeoutMillis = timeoutMillis;
}
makeFullUrl(url) {
return this.urlPrefix + url;
}
makeAcceptHeader(successType) {
const types = new Set([successType, this.validErrorDecoder.contentType, this.authErrorDecoder.contentType]);
return Array.from(types).join(", ");
}
handleResponse(resp, successParser) {
const promise = new Promise((resolve, reject) => {
resp
.then(response => {
const result = new result_1.Success(successParser.decode(response.data));
resolve(result);
})
.catch(err => {
const response = err.response;
if (response) {
switch (response.status) {
case 400:
resolve(new result_1.ValidError(this.validErrorDecoder.decode(response.data)));
break;
case 401:
case 403:
resolve(new result_1.AuthError(this.authErrorDecoder.decode(response.data)));
break;
default:
console.error("An unexpected API error occurred", response);
resolve(new result_1.InternalError(`${response.status} - ${response.statusText}`));
}
}
else {
resolve(new result_1.UnreachableError());
}
});
});
return (0, result_1.futureResultFromPromise)(promise);
}
post(url, s, encoder, decoder) {
const fullUrl = this.makeFullUrl(url);
const payload = encoder.encode(s);
const resp = axios_1.default
.post(fullUrl, payload, {
headers: {
"Content-Type": encoder.contentType,
"Accept": this.makeAcceptHeader(decoder.contentType)
},
responseType: "arraybuffer",
timeout: this.timeoutMillis
});
return this.handleResponse(resp, decoder);
}
put(url, s, encoder, decoder) {
const fullUrl = this.makeFullUrl(url);
const payload = encoder.encode(s);
const resp = axios_1.default
.put(fullUrl, payload, {
headers: {
"Content-Type": encoder.contentType,
"Accept": this.makeAcceptHeader(decoder.contentType)
},
responseType: "arraybuffer",
timeout: this.timeoutMillis
});
return this.handleResponse(resp, decoder);
}
get(url, decoder) {
const fullUrl = this.makeFullUrl(url);
const resp = axios_1.default
.get(fullUrl, {
responseType: "arraybuffer",
timeout: this.timeoutMillis,
headers: {
"Accept": this.makeAcceptHeader(decoder.contentType)
}
});
return this.handleResponse(resp, decoder);
}
delete(url, decoder) {
const fullUrl = this.makeFullUrl(url);
const resp = axios_1.default
.delete(fullUrl, {
responseType: "arraybuffer",
timeout: this.timeoutMillis,
headers: {
"Accept": this.makeAcceptHeader(decoder.contentType)
}
});
return this.handleResponse(resp, decoder);
}
}
exports.API = API;