polarity-integration-utils 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -0
  3. package/dist/es/errors/RequestError.js +12 -0
  4. package/dist/es/errors/index.js +11 -0
  5. package/dist/es/errors/parseErrorToReadableJson.js +4 -0
  6. package/dist/es/helpers/async/index.js +9 -0
  7. package/dist/es/helpers/async/parallelLimit.js +33 -0
  8. package/dist/es/helpers/encodings/decodeBase64.js +4 -0
  9. package/dist/es/helpers/encodings/encodeBase64.js +4 -0
  10. package/dist/es/helpers/encodings/index.js +11 -0
  11. package/dist/es/helpers/index.js +10 -0
  12. package/dist/es/helpers/json/and.js +4 -0
  13. package/dist/es/helpers/json/filterObjectsContainingString.js +10 -0
  14. package/dist/es/helpers/json/index.js +17 -0
  15. package/dist/es/helpers/json/mapOverObject.js +24 -0
  16. package/dist/es/helpers/json/or.js +4 -0
  17. package/dist/es/helpers/json/transpose2dArray.js +8 -0
  18. package/dist/es/helpers/time/index.js +11 -0
  19. package/dist/es/helpers/time/millisecondsToHoursMinutesAndSeconds.js +18 -0
  20. package/dist/es/helpers/time/sleep.js +13 -0
  21. package/dist/es/index.js +16 -0
  22. package/dist/es/logging/index.js +4 -0
  23. package/dist/es/logging/logger.js +17 -0
  24. package/dist/es/requests/createRequestWithDefaults.js +166 -0
  25. package/dist/es/requests/createRequestsInParallel.js +40 -0
  26. package/dist/es/requests/index.js +11 -0
  27. package/dist/es/requests/requestTypes.js +2 -0
  28. package/dist/es/user-options/index.js +9 -0
  29. package/dist/es/user-options/validateUrlOption.js +77 -0
  30. package/dist/lib/errors/RequestError.js +12 -0
  31. package/dist/lib/errors/index.js +11 -0
  32. package/dist/lib/errors/parseErrorToReadableJson.js +4 -0
  33. package/dist/lib/helpers/async/index.js +9 -0
  34. package/dist/lib/helpers/async/parallelLimit.js +33 -0
  35. package/dist/lib/helpers/encodings/decodeBase64.js +4 -0
  36. package/dist/lib/helpers/encodings/encodeBase64.js +4 -0
  37. package/dist/lib/helpers/encodings/index.js +11 -0
  38. package/dist/lib/helpers/index.js +10 -0
  39. package/dist/lib/helpers/json/and.js +4 -0
  40. package/dist/lib/helpers/json/filterObjectsContainingString.js +10 -0
  41. package/dist/lib/helpers/json/index.js +17 -0
  42. package/dist/lib/helpers/json/mapOverObject.js +24 -0
  43. package/dist/lib/helpers/json/or.js +4 -0
  44. package/dist/lib/helpers/json/transpose2dArray.js +8 -0
  45. package/dist/lib/helpers/time/index.js +11 -0
  46. package/dist/lib/helpers/time/millisecondsToHoursMinutesAndSeconds.js +18 -0
  47. package/dist/lib/helpers/time/sleep.js +13 -0
  48. package/dist/lib/index.js +16 -0
  49. package/dist/lib/logging/index.js +4 -0
  50. package/dist/lib/logging/logger.js +17 -0
  51. package/dist/lib/requests/createRequestWithDefaults.js +166 -0
  52. package/dist/lib/requests/createRequestsInParallel.js +40 -0
  53. package/dist/lib/requests/index.js +11 -0
  54. package/dist/lib/requests/requestTypes.js +2 -0
  55. package/dist/lib/user-options/index.js +9 -0
  56. package/dist/lib/user-options/validateUrlOption.js +77 -0
  57. package/package.json +42 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2017 Breach Intelligence, Inc., 2020 Polarity.IO Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Polarity Integration Utils
2
+
3
+ This library is intended for use in development of Polarity Integrations.
4
+
5
+
6
+
7
+ ## Contribution Instructions
8
+
9
+ > NOTE: Don't forget to add your implementations to the `./test/index.test.js` to ensure your implementation is accessible from the main index.js
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class RequestError extends Error {
4
+ constructor(message, status, description, requestOptions) {
5
+ super();
6
+ this.message = `Request Error${message ? ` -> ${message}` : ''}`;
7
+ this.status = status;
8
+ this.description = description;
9
+ this.requestOptions = requestOptions;
10
+ }
11
+ }
12
+ exports.default = RequestError;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const parseErrorToReadableJson_1 = __importDefault(require("./parseErrorToReadableJson"));
7
+ const RequestError_1 = __importDefault(require("./RequestError"));
8
+ exports.default = {
9
+ parseErrorToReadableJson: parseErrorToReadableJson_1.default,
10
+ RequestError: RequestError_1.default
11
+ };
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const parseErrorToReadableJson = (error) => JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));
4
+ exports.default = parseErrorToReadableJson;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const parallelLimit_1 = __importDefault(require("./parallelLimit"));
7
+ exports.default = {
8
+ parallelLimit: parallelLimit_1.default
9
+ };
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const parallelLimit = (tasksQueue, simultaneousTaskRunningLimit, returnErrors = false) => __awaiter(void 0, void 0, void 0, function* () {
13
+ const results = [];
14
+ const runTasks = (tasksIterator) => __awaiter(void 0, void 0, void 0, function* () {
15
+ for (const [index, task] of tasksIterator) {
16
+ try {
17
+ results[index] = yield task();
18
+ }
19
+ catch (error) {
20
+ if (returnErrors)
21
+ results[index] = error;
22
+ else
23
+ throw error;
24
+ }
25
+ }
26
+ });
27
+ const workers = new Array(simultaneousTaskRunningLimit)
28
+ .fill(tasksQueue.entries())
29
+ .map(runTasks);
30
+ yield Promise.allSettled(workers);
31
+ return results;
32
+ });
33
+ exports.default = parallelLimit;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const decodeBase64 = (str) => str && Buffer.from(str, 'base64').toString('ascii');
4
+ exports.default = decodeBase64;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const encodeBase64 = (str) => str && Buffer.from(str).toString('base64');
4
+ exports.default = encodeBase64;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const encodeBase64_1 = __importDefault(require("./encodeBase64"));
7
+ const decodeBase64_1 = __importDefault(require("./decodeBase64"));
8
+ exports.default = {
9
+ encodeBase64: encodeBase64_1.default,
10
+ decodeBase64: decodeBase64_1.default
11
+ };
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const time_1 = __importDefault(require("./time"));
7
+ const json_1 = __importDefault(require("./json"));
8
+ const encodings_1 = __importDefault(require("./encodings"));
9
+ const async_1 = __importDefault(require("./async"));
10
+ exports.default = Object.assign(Object.assign(Object.assign(Object.assign({}, time_1.default), json_1.default), encodings_1.default), async_1.default);
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const and = (...[func, ...funcs]) => (x) => !!func(x) && (funcs.length ? !!and.apply(null, funcs)(x) : true);
4
+ exports.default = and;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fp_1 = require("lodash/fp");
4
+ const filterObjectsContainingString = (0, fp_1.curry)((string, objs = []) => {
5
+ const modifiedSearchString = (0, fp_1.flow)((0, fp_1.replace)(/[^\w]/g, ''), fp_1.toLower)(string);
6
+ if (!modifiedSearchString)
7
+ return [];
8
+ return (0, fp_1.filter)((0, fp_1.flow)(JSON.stringify, (0, fp_1.replace)(/[^\w]/g, ''), fp_1.toLower, (0, fp_1.includes)(modifiedSearchString)), objs);
9
+ });
10
+ exports.default = filterObjectsContainingString;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const transpose2dArray_1 = __importDefault(require("./transpose2dArray"));
7
+ const mapOverObject_1 = __importDefault(require("./mapOverObject"));
8
+ const filterObjectsContainingString_1 = __importDefault(require("./filterObjectsContainingString"));
9
+ const and_1 = __importDefault(require("./and"));
10
+ const or_1 = __importDefault(require("./or"));
11
+ exports.default = {
12
+ transpose2dArray: transpose2dArray_1.default,
13
+ mapOverObject: mapOverObject_1.default,
14
+ filterObjectsContainingString: filterObjectsContainingString_1.default,
15
+ and: and_1.default,
16
+ or: or_1.default
17
+ };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fp_1 = require("lodash/fp");
7
+ const and_1 = __importDefault(require("./and"));
8
+ /**
9
+ * Function to map over properties in an object.
10
+ * This allows for transformations on both the keys and values of each properties.
11
+ * This function also supports currying
12
+ *
13
+ * @param func - function that takes in `value` & `key' from each object property and
14
+ * returns a new key and new value in an array of length 2
15
+ * e.g. (value, key) => [newKey, newValue]
16
+ * @param obj - JSON object which we wish to map over the properties of
17
+ * e.g. { key1: value1, key2: value2 }
18
+ * @returns - JSON object with the transformed keys and values for each property
19
+ * e.g. { newKey1: newValue1, newKey2: newValue2 }
20
+ */
21
+ const mapOverObject = (0, fp_1.curry)((func, obj) => obj && (0, fp_1.isPlainObject)(obj)
22
+ ? (0, fp_1.flow)(Object.entries, (0, fp_1.map)(([key, value]) => func(value, key)), (0, fp_1.filter)((0, and_1.default)((0, fp_1.negate)(fp_1.isEmpty), (0, fp_1.flow)(fp_1.size, (0, fp_1.eq)(2)))), Object.fromEntries)(obj)
23
+ : obj);
24
+ exports.default = mapOverObject;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const or = (...[func, ...funcs]) => (x) => !!func(x) || (!!funcs.length && !!or.apply(null, funcs)(x));
4
+ exports.default = or;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fp_1 = require("lodash/fp");
4
+ const transpose2dArray = (twoDimensionalArray) => (0, fp_1.reduce)((agg, [key, value]) => [
5
+ [...agg[0], key],
6
+ [...agg[1], value]
7
+ ], [[], []], twoDimensionalArray);
8
+ exports.default = transpose2dArray;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const sleep_1 = __importDefault(require("./sleep"));
7
+ const millisecondsToHoursMinutesAndSeconds_1 = __importDefault(require("./millisecondsToHoursMinutesAndSeconds"));
8
+ exports.default = {
9
+ sleep: sleep_1.default,
10
+ millisecondsToHoursMinutesAndSeconds: millisecondsToHoursMinutesAndSeconds_1.default
11
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const millisecondsToHoursMinutesAndSeconds = (milliseconds = 0) => {
4
+ if (typeof milliseconds !== 'number' || isNaN(milliseconds)) {
5
+ throw new Error(`Cannot calculate Hours, Minutes, or Seconds from non-number input: \`${milliseconds}\``);
6
+ }
7
+ let remainingMilliseconds = milliseconds;
8
+ const seconds = Math.floor((remainingMilliseconds / 1000) % 60);
9
+ remainingMilliseconds -= seconds * 1000;
10
+ const minutes = Math.floor((remainingMilliseconds / 60000) % 60);
11
+ remainingMilliseconds -= minutes * 60000;
12
+ const hours = Math.floor(remainingMilliseconds / 3600000);
13
+ return ((hours ? `${hours} hours${minutes || seconds ? ', ' : ''}` : '') +
14
+ (minutes ? `${minutes} minutes${seconds ? ', ' : ''}` : '') +
15
+ (seconds ? `${seconds} seconds` : '') +
16
+ (!hours && !minutes && !seconds ? `${milliseconds}ms` : ''));
17
+ };
18
+ exports.default = millisecondsToHoursMinutesAndSeconds;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const sleep = (ms = 2000) => __awaiter(void 0, void 0, void 0, function* () { return new Promise((r) => setTimeout(r, ms)); });
13
+ exports.default = sleep;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.userOptions = exports.logging = exports.requests = exports.helpers = exports.errors = void 0;
7
+ const errors_1 = __importDefault(require("./errors"));
8
+ exports.errors = errors_1.default;
9
+ const helpers_1 = __importDefault(require("./helpers"));
10
+ exports.helpers = helpers_1.default;
11
+ const requests_1 = __importDefault(require("./requests"));
12
+ exports.requests = requests_1.default;
13
+ const logging_1 = __importDefault(require("./logging"));
14
+ exports.logging = logging_1.default;
15
+ const user_options_1 = __importDefault(require("./user-options"));
16
+ exports.userOptions = user_options_1.default;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const logger_1 = require("./logger");
4
+ exports.default = { getLogger: logger_1.getLogger, setLogger: logger_1.setLogger };
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getLogger = exports.setLogger = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const fp_1 = require("lodash/fp");
9
+ const loggingLevels = ['info', 'debug', 'trace', 'warn', 'error', 'fatal'];
10
+ const writeToDevRunnerResults = (loggingLevel) => (...content) => fs_1.default.appendFileSync('devRunnerResults.json', '\n' + JSON.stringify({ SOURCE: `Logger.${loggingLevel}`, content }, null, 2));
11
+ let logger = (0, fp_1.flow)((0, fp_1.reduce)((agg, level) => (Object.assign(Object.assign({}, agg), { [level]: writeToDevRunnerResults(level) })), {}))(loggingLevels);
12
+ const setLogger = (_logger) => {
13
+ logger = _logger;
14
+ };
15
+ exports.setLogger = setLogger;
16
+ const getLogger = () => logger;
17
+ exports.getLogger = getLogger;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.requestWithDefaultsBuilder = void 0;
16
+ const fs = require("fs");
17
+ const postman_request_1 = __importDefault(require("postman-request"));
18
+ const fp_1 = require("lodash/fp");
19
+ const bottleneck_1 = __importDefault(require("bottleneck"));
20
+ const logging_1 = __importDefault(require("../logging"));
21
+ const errors_1 = __importDefault(require("../errors"));
22
+ const _configFieldIsValid = (field) => typeof field === 'string' && field.length > 0;
23
+ let limiter;
24
+ function _setupLimiter(options) {
25
+ limiter = new bottleneck_1.default({
26
+ maxConcurrent: options.maxConcurrentRequests
27
+ ? Number.parseInt(options.maxConcurrentRequests, 10)
28
+ : 10,
29
+ highWater: 50,
30
+ strategy: bottleneck_1.default.strategy.OVERFLOW,
31
+ minTime: options.minimumMillisecondsRequestWillTake
32
+ ? Number.parseInt(options.minimumMillisecondsRequestWillTake, 10)
33
+ : 200
34
+ });
35
+ }
36
+ /**
37
+ * @param interface CreateRequestFunctionArguments {
38
+ * config?: type ConfigJs = {
39
+ * request: {
40
+ * ca?: string;
41
+ * cert?: string;
42
+ * key?: string;
43
+ * passphrase?: string;
44
+ * rejectUnauthorized?: string;
45
+ * proxy?: string;
46
+ * json?: boolean;
47
+ * };
48
+ * } | undefined;
49
+ * * The entire config.js(on) object
50
+ * roundedSuccessStatusCode?: number[];
51
+ * * Defaults: [200]
52
+ * * Status codes, rounded to the 100's place, that should not throw errors.
53
+ * useLimiter?: boolean;
54
+ * * Defaults: false
55
+ * * Set limit params in options (options.maxConcurrentRequests [default 10] & options.minimumMillisecondsRequestWillTake [default 200]) passed when
56
+ * using the RequestWithDefaultsFunction this function returns
57
+ * which can be hardcoded or can come from the userOptions directly
58
+ * requestOptionsToOmitFromLogsKeyPaths?: string[];
59
+ * * Defaults: ['headers.Authorization']
60
+ * * Key Paths on the Request Options you wish to not automatically log.
61
+ * preprocessRequestOptions?: type PreprocessRequestOptionsFunction =
62
+ * (requestOptions: RequestOptions) => Promise<object> | never | undefined;
63
+ * postprocessRequestResponse?: type PostprocessRequestResponseFunction =
64
+ * (response: any, requestOptions: RequestOptions) => Promise<any> | never | undefined;
65
+ * postprocessRequestFailure?: type PostprocessRequestFailureFunction =
66
+ * (error: Error, requestOptions: RequestOptions) => Promise<any> | never | undefined;
67
+ * }
68
+ * @returns type RequestWithDefaultsFunction = (requestOptions: RequestOptions) => Promise<any> | never
69
+ * * Returns an async request function with the proxy defaults included in the request options
70
+ * * type RequestOptions = {
71
+ * url?: string;
72
+ * headers?: object;
73
+ * qs?: object;
74
+ * options?: object;
75
+ * entity?: object;
76
+ * form?: object;
77
+ * [key: string]: any;
78
+ * }
79
+ };
80
+ */
81
+ const createRequestWithDefaults = ({ config: { request: { ca, cert, key, passphrase, rejectUnauthorized, proxy, json } } = {
82
+ request: {
83
+ ca: '',
84
+ cert: '',
85
+ key: '',
86
+ passphrase: '',
87
+ proxy: '',
88
+ rejectUnauthorized: false,
89
+ json: true
90
+ }
91
+ }, roundedSuccessStatusCodes = [200], useLimiter = false, requestOptionsToOmitFromLogsKeyPaths = ['headers.Authorization'], preprocessRequestOptions = (requestOptions) => __awaiter(void 0, void 0, void 0, function* () { return ({}); }), postprocessRequestResponse = (response, requestOptions) => __awaiter(void 0, void 0, void 0, function* () { return response; }), postprocessRequestFailure = (error, requestOptions) => __awaiter(void 0, void 0, void 0, function* () {
92
+ throw error;
93
+ }) }) => {
94
+ const defaultsProxyOptions = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (_configFieldIsValid(ca) && { ca: fs.readFileSync(ca) })), (_configFieldIsValid(cert) && { cert: fs.readFileSync(cert) })), (_configFieldIsValid(key) && { key: fs.readFileSync(key) })), (_configFieldIsValid(passphrase) && { passphrase })), (_configFieldIsValid(proxy) && { proxy })), (typeof rejectUnauthorized === 'boolean' && { rejectUnauthorized })), { json });
95
+ const requestDefaultsWithInterceptors = (0, exports.requestWithDefaultsBuilder)(defaultsProxyOptions, roundedSuccessStatusCodes, useLimiter, requestOptionsToOmitFromLogsKeyPaths, preprocessRequestOptions, postprocessRequestResponse, postprocessRequestFailure);
96
+ return requestDefaultsWithInterceptors;
97
+ };
98
+ const requestWithDefaultsBuilder = (defaultsProxyOptions, roundedSuccessStatusCodes, useLimiter, requestOptionsToOmitFromLogsKeyPaths, preprocessRequestOptions, postprocessRequestResponse, postprocessRequestFailure) => {
99
+ const defaultsRequest = postman_request_1.default.defaults(defaultsProxyOptions);
100
+ const _requestWithDefaults = (requestOptions) => new Promise((resolve, reject) => {
101
+ defaultsRequest(requestOptions, (err, res) => {
102
+ if (err)
103
+ return reject(err);
104
+ resolve(res);
105
+ });
106
+ });
107
+ return (requestOptions) => __awaiter(void 0, void 0, void 0, function* () {
108
+ if (useLimiter && !limiter)
109
+ _setupLimiter(requestOptions.options);
110
+ const preRequestFunctionResults = yield preprocessRequestOptions(requestOptions);
111
+ const _requestOptions = Object.assign(Object.assign({}, requestOptions), preRequestFunctionResults);
112
+ let postRequestFunctionResults, result;
113
+ try {
114
+ result = yield (useLimiter
115
+ ? limiter.schedule(_requestWithDefaults, _requestOptions)
116
+ : _requestWithDefaults(_requestOptions));
117
+ checkForStatusError(result, _requestOptions, roundedSuccessStatusCodes, requestOptionsToOmitFromLogsKeyPaths);
118
+ postRequestFunctionResults = yield postprocessRequestResponse(result, _requestOptions);
119
+ }
120
+ catch (error) {
121
+ try {
122
+ postRequestFunctionResults = yield postprocessRequestFailure(error, _requestOptions);
123
+ }
124
+ catch (error) {
125
+ const err = errors_1.default.parseErrorToReadableJson(error);
126
+ if (useLimiter) {
127
+ error.maxRequestQueueLimitHit =
128
+ ((0, fp_1.isEmpty)(err) && (0, fp_1.isEmpty)(result)) ||
129
+ (err &&
130
+ (err.message ===
131
+ 'This job has been dropped by Bottleneck for going over API Limits' ||
132
+ err instanceof bottleneck_1.default.BottleneckError));
133
+ error.isConnectionReset =
134
+ (0, fp_1.getOr)('', 'errors[0].meta.err.code', err) === 'ECONNRESET';
135
+ }
136
+ if (_requestOptions.entity)
137
+ error.entity = JSON.stringify(_requestOptions.entity);
138
+ throw error;
139
+ }
140
+ }
141
+ return postRequestFunctionResults;
142
+ });
143
+ };
144
+ exports.requestWithDefaultsBuilder = requestWithDefaultsBuilder;
145
+ const checkForStatusError = ({ statusCode, body }, requestOptions, roundedSuccessStatusCodes, requestOptionsToOmitFromLogsKeyPaths) => {
146
+ const Logger = logging_1.default.getLogger();
147
+ const requestOptionsWithoutSensitiveData = (0, fp_1.omit)(requestOptionsToOmitFromLogsKeyPaths.concat('options'), requestOptions);
148
+ Logger.trace({
149
+ MESSAGE: 'Request Ran, Checking Status...',
150
+ statusCode,
151
+ requestOptions: requestOptionsWithoutSensitiveData,
152
+ responseBody: body
153
+ });
154
+ const roundedStatus = Math.round(statusCode / 100) * 100;
155
+ const statusCodeNotSuccessful = !roundedSuccessStatusCodes.includes(roundedStatus);
156
+ const responseBodyError = (0, fp_1.get)('error', body);
157
+ if (statusCodeNotSuccessful || responseBodyError) {
158
+ const message = (0, fp_1.get)('message', responseBodyError);
159
+ const status = statusCodeNotSuccessful ? statusCode : (0, fp_1.get)('code', responseBodyError);
160
+ const description = JSON.stringify(body);
161
+ const requestOptions = JSON.stringify(requestOptionsWithoutSensitiveData);
162
+ const requestError = new errors_1.default.RequestError(message, status, description, requestOptions);
163
+ throw requestError;
164
+ }
165
+ };
166
+ exports.default = createRequestWithDefaults;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const fp_1 = require("lodash/fp");
27
+ const helpers_1 = __importDefault(require("../helpers"));
28
+ const createRequestsInParallel = (requestWithDefaults) => (allRequestsOptions, responseGetPath = 'body', possibleSimultaneousRequests = 10, returnErrors = false) => __awaiter(void 0, void 0, void 0, function* () {
29
+ const unexecutedRequestFunctions = (0, fp_1.map)((_a) => {
30
+ var { entity } = _a, requestOptions = __rest(_a, ["entity"]);
31
+ return () => __awaiter(void 0, void 0, void 0, function* () {
32
+ const response = yield requestWithDefaults(requestOptions);
33
+ const result = responseGetPath ? (0, fp_1.get)(responseGetPath, response) : response;
34
+ return entity ? { entity, result } : result;
35
+ });
36
+ }, allRequestsOptions);
37
+ const results = yield helpers_1.default.parallelLimit(unexecutedRequestFunctions, possibleSimultaneousRequests, returnErrors);
38
+ return results;
39
+ });
40
+ exports.default = createRequestsInParallel;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const createRequestWithDefaults_1 = __importDefault(require("./createRequestWithDefaults"));
7
+ const createRequestsInParallel_1 = __importDefault(require("./createRequestsInParallel"));
8
+ exports.default = {
9
+ createRequestWithDefaults: createRequestWithDefaults_1.default,
10
+ createRequestsInParallel: createRequestsInParallel_1.default
11
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const validateUrlOption_1 = __importDefault(require("./validateUrlOption"));
7
+ exports.default = {
8
+ validateUrlOption: validateUrlOption_1.default
9
+ };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fp_1 = require("lodash/fp");
4
+ /**
5
+ *
6
+ * @param {object} options - User Options from the inside of validate options
7
+ * e.g. each user option contains a metadata object including the value
8
+ * { userOption1: { value: 'user option input' ...moreOptionMetadata } }
9
+ * @param {string} urlKey - [ default='url' ] The key of the url inside of the user options
10
+ * defined via the `./config/config.js(on)` `options.?.key` property value.
11
+ * Generally if there is only 1 url user option, the `key` property should be set to
12
+ * `url` so the default option here can be used. If there are more than 1 url in the
13
+ * user options giving the `options.?.key` properties different value is expected.
14
+ * @param {array<objects>} otherValidationErrors - [ default=[] ] Allows you to pass in
15
+ * existing validation error objects that will have any new validation errors found
16
+ * added onto the end before returned.
17
+ * [
18
+ * {
19
+ * key: 'otherUserOptionKey',
20
+ * message: 'Description of something wrong with the users input for this user option.'
21
+ * }
22
+ * ]
23
+ *
24
+ * @returns {array<objects> || throws} Any URL based Validation Error found in relation to the user option
25
+ * for the `urlKey` param found on the `options param
26
+ * [
27
+ * ...otherValidationErrors
28
+ * {
29
+ * key: 'url',
30
+ * message: '* Required'
31
+ * },
32
+ * // OR
33
+ * {
34
+ * key: 'url',
35
+ * message: 'Your Url must not end with a //'
36
+ * },
37
+ * // OR
38
+ * {
39
+ * key: 'url',
40
+ * message: 'What is currently provided is not a valid URL. You must provide a valid Instance URL.'
41
+ * },
42
+ * ]
43
+ */
44
+ const validateUrlOption = (options, urlKey = 'url', otherValidationErrors = []) => {
45
+ const urlValue = (0, fp_1.get)([urlKey, 'value'], options);
46
+ if (urlValue === undefined) {
47
+ throw new Error(`User Option key \`${urlKey}\` is not defined in the config.js. ` +
48
+ "It's also possible you need to change the package.json version for the client to pick up your `config/config.js` changes.");
49
+ }
50
+ let allValidationErrors = otherValidationErrors;
51
+ // TODO: Add support & tests for non-required urls or remove the `required` input value check if the situation where desire for use of this feature is encountered
52
+ if (!urlValue) {
53
+ allValidationErrors = allValidationErrors.concat({
54
+ key: urlKey,
55
+ message: '* Required'
56
+ });
57
+ }
58
+ if (urlValue.endsWith('//')) {
59
+ allValidationErrors = allValidationErrors.concat({
60
+ key: urlKey,
61
+ message: 'Your Url must not end with a //'
62
+ });
63
+ }
64
+ if (urlValue) {
65
+ try {
66
+ new URL(urlValue);
67
+ }
68
+ catch (_) {
69
+ allValidationErrors = allValidationErrors.concat({
70
+ key: urlKey,
71
+ message: 'What is currently provided is not a valid URL. You must provide a valid Instance URL.'
72
+ });
73
+ }
74
+ }
75
+ return allValidationErrors;
76
+ };
77
+ exports.default = validateUrlOption;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class RequestError extends Error {
4
+ constructor(message, status, description, requestOptions) {
5
+ super();
6
+ this.message = `Request Error${message ? ` -> ${message}` : ''}`;
7
+ this.status = status;
8
+ this.description = description;
9
+ this.requestOptions = requestOptions;
10
+ }
11
+ }
12
+ exports.default = RequestError;