UNPKG

react-api-adts

Version:

Helpful algebraic data types for API handling in React apps.

125 lines (124 loc) 4.45 kB
"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;