UNPKG

@ne1410s/http

Version:

Lightweight ES5 script to provide http utilities

403 lines (383 loc) 18.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@ne1410s/codl'), require('jws')) : typeof define === 'function' && define.amd ? define(['exports', '@ne1410s/codl', 'jws'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ne_http = {}, global.ne_codl, global.jws)); })(this, (function (exports, codl, jws) { 'use strict'; function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var jws__namespace = /*#__PURE__*/_interopNamespaceDefault(jws); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /** * Thrown when a model is deemed to be invalid. */ var ValidationError = /** @class */ (function (_super) { __extends(ValidationError, _super); function ValidationError(message, model, errors) { var _this = _super.call(this, message) || this; _this.message = message; _this.model = model; _this.errors = errors; return _this; } return ValidationError; }(Error)); /** * Thrown when an operation was not invoked successfully. */ var OperationInvocationError = /** @class */ (function (_super) { __extends(OperationInvocationError, _super); function OperationInvocationError(message, operation, request, cause) { var _this = _super.call(this, message) || this; _this.message = message; _this.operation = operation; _this.request = request; _this.cause = cause; return _this; } return OperationInvocationError; }(Error)); /** * Thrown when an http response is deemed to be unworkable. */ var HttpResponseError = /** @class */ (function (_super) { __extends(HttpResponseError, _super); function HttpResponseError(response, verb) { var _this = _super.call(this, 'Unexpected response') || this; _this.verb = verb; _this.headers = {}; response.headers.forEach(function (val, key) { return (_this.headers[key] = val); }); response.text().then(function (body) { return (_this.body = body); }); _this.statusCode = response.status; _this.statusText = response.statusText; _this.url = response.url; return _this; } return HttpResponseError; }(Error)); /** * Base implementation for that which generates a response from a request. */ var OperationBase = /** @class */ (function () { /** * Creates a new instance. Parameters are model prototypes. They are only * needed if automatic validation (of @ne1410s/codl decorators) is required. * @param requestType The request type. * @param responseType The response type. */ function OperationBase(requestType, responseType) { this.requestType = requestType; this.responseType = responseType; } /** * @inheritdoc */ OperationBase.prototype.invoke = function (requestData) { return __awaiter(this, void 0, void 0, function () { var responseData, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: this.validateRequest(requestData); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.invokeInternal(requestData)]; case 2: responseData = _a.sent(); return [3 /*break*/, 4]; case 3: error_1 = _a.sent(); throw new OperationInvocationError('An error occurred invoking the operation', this, requestData, error_1); case 4: this.validateResponse(responseData); return [2 /*return*/, responseData]; } }); }); }; /** Validates a request according to @ne1410s/codl decorators. */ OperationBase.prototype.validateRequest = function (requestData) { if (!this.requestType) return; var summary = codl.ReflectValidation.validate(requestData, this.requestType); if (!summary.valid) { var errors = []; for (var key in summary.errors) { errors.push.apply(errors, summary.errors[key]); } throw new ValidationError('The request is invalid', requestData, errors); } }; /** Validates the response according to @ne1410s/codl decorators. */ OperationBase.prototype.validateResponse = function (responseData) { if (!this.responseType) return; var summary = codl.ReflectValidation.validate(responseData, this.responseType); if (!summary.valid) { var errors = []; for (var key in summary.errors) { errors.push.apply(errors, summary.errors[key]); } throw new ValidationError('The response is invalid', responseData, errors); } }; return OperationBase; }()); /** * Thrown when serialisation was not successful. */ var SerialisationError = /** @class */ (function (_super) { __extends(SerialisationError, _super); function SerialisationError(message, model, cause) { var _this = _super.call(this, message) || this; _this.message = message; _this.model = model; _this.cause = cause; return _this; } return SerialisationError; }(Error)); /** * Thrown when deserialisation was not successful. */ var DeserialisationError = /** @class */ (function (_super) { __extends(DeserialisationError, _super); function DeserialisationError(message, cause) { var _this = _super.call(this, message) || this; _this.message = message; _this.cause = cause; return _this; } return DeserialisationError; }(Error)); require('isomorphic-fetch'); var HttpOperation = /** @class */ (function (_super) { __extends(HttpOperation, _super); function HttpOperation(url, verb, headers, requestType, responseType) { if (verb === void 0) { verb = 'get'; } var _this = _super.call(this, requestType, responseType) || this; _this.verb = verb; _this.headers = new Headers(headers || []); _this._url = url; return _this; } Object.defineProperty(HttpOperation.prototype, "url", { get: function () { return this._url; }, enumerable: false, configurable: true }); /** * @inheritdoc * @throws {SerialisationError} * @throws {DeserialisationError} */ HttpOperation.prototype.invokeInternal = function (requestData) { return __awaiter(this, void 0, void 0, function () { var runUrl, runParams, _a, error_1, response, error_2; return __generator(this, function (_b) { switch (_b.label) { case 0: runUrl = this.url; runParams = { method: this.verb, headers: this.headers, }; if (!(requestData != null)) return [3 /*break*/, 6]; _b.label = 1; case 1: _b.trys.push([1, 5, , 6]); if (!(this.verb === 'get' || this.verb === 'head')) return [3 /*break*/, 2]; runUrl = "".concat(this.url, "?").concat(this.serialiseQuery(requestData)); return [3 /*break*/, 4]; case 2: _a = runParams; return [4 /*yield*/, this.serialise(requestData)]; case 3: _a.body = _b.sent(); _b.label = 4; case 4: return [3 /*break*/, 6]; case 5: error_1 = _b.sent(); throw new SerialisationError('An error occurred serialising the request', requestData, error_1); case 6: return [4 /*yield*/, fetch(runUrl, runParams)]; case 7: response = _b.sent(); _b.label = 8; case 8: _b.trys.push([8, 10, , 11]); return [4 /*yield*/, this.deserialise(response, requestData)]; case 9: return [2 /*return*/, _b.sent()]; case 10: error_2 = _b.sent(); throw new DeserialisationError('An error occurred deserialising the response', error_2); case 11: return [2 /*return*/]; } }); }); }; HttpOperation.prototype.serialiseQuery = function (requestData) { return Object.keys(requestData) .map(function (k) { return k + '=' + encodeURIComponent(requestData[k]); }) .join('&'); }; return HttpOperation; }(OperationBase)); var JsonOperation = /** @class */ (function (_super) { __extends(JsonOperation, _super); function JsonOperation(url, verb, headers, requestType, responseType) { if (verb === void 0) { verb = 'get'; } var _this = _super.call(this, url, verb, headers, requestType, responseType) || this; _this.headers.set('content-type', 'application/json'); _this.headers.set('accept', 'application/json'); return _this; } /** * @inheritdoc */ JsonOperation.prototype.serialise = function (requestData) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Promise.resolve()]; case 1: _a.sent(); return [2 /*return*/, requestData ? JSON.stringify(requestData) : null]; } }); }); }; /** * @inheritdoc */ JsonOperation.prototype.deserialise = function (response, requestData) { return __awaiter(this, void 0, void 0, function () { var raw; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, response.text()]; case 1: raw = _a.sent(); return [2 /*return*/, JSON.parse(raw)]; } }); }); }; return JsonOperation; }(HttpOperation)); var JsonBodylessOperation = /** @class */ (function (_super) { __extends(JsonBodylessOperation, _super); function JsonBodylessOperation(url, verb, headers, responseType) { if (verb === void 0) { verb = 'get'; } return _super.call(this, url, verb, headers, null, responseType) || this; } JsonBodylessOperation.prototype.invoke = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, _super.prototype.invoke.call(this, null)]; }); }); }; return JsonBodylessOperation; }(JsonOperation)); /** A client for consuming json web tokens. */ var JwtClient = /** @class */ (function () { function JwtClient() { } /** Parses the contents of a token. */ JwtClient.parse = function (token) { return JSON.parse(jws__namespace.decode(token).payload); }; return JwtClient; }()); exports.DeserialisationError = DeserialisationError; exports.HttpOperation = HttpOperation; exports.HttpResponseError = HttpResponseError; exports.JsonBodylessOperation = JsonBodylessOperation; exports.JsonOperation = JsonOperation; exports.JwtClient = JwtClient; exports.OperationBase = OperationBase; exports.OperationInvocationError = OperationInvocationError; exports.SerialisationError = SerialisationError; exports.ValidationError = ValidationError; }));