polarity-integration-utils 0.1.0 → 3.1.3
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.
- package/README.md +30 -2
- package/dist/dts/context/cache.d.ts +149 -0
- package/dist/dts/context/cache.d.ts.map +1 -0
- package/dist/dts/context/index.d.ts +3 -0
- package/dist/dts/context/index.d.ts.map +1 -0
- package/dist/dts/context/integration-context.d.ts +16 -0
- package/dist/dts/context/integration-context.d.ts.map +1 -0
- package/dist/dts/errors/api-request-error.d.ts +10 -0
- package/dist/dts/errors/api-request-error.d.ts.map +1 -0
- package/dist/dts/errors/auth-request-error.d.ts +10 -0
- package/dist/dts/errors/auth-request-error.d.ts.map +1 -0
- package/dist/dts/errors/index.d.ts +8 -0
- package/dist/dts/errors/index.d.ts.map +1 -0
- package/dist/dts/errors/integration-error.d.ts +189 -0
- package/dist/dts/errors/integration-error.d.ts.map +1 -0
- package/dist/dts/errors/library-usage-error.d.ts +12 -0
- package/dist/dts/errors/library-usage-error.d.ts.map +1 -0
- package/dist/dts/errors/network-error.d.ts +11 -0
- package/dist/dts/errors/network-error.d.ts.map +1 -0
- package/dist/dts/errors/parse-error-to-readable-json.d.ts +7 -0
- package/dist/dts/errors/parse-error-to-readable-json.d.ts.map +1 -0
- package/dist/dts/errors/retry-request-error.d.ts +11 -0
- package/dist/dts/errors/retry-request-error.d.ts.map +1 -0
- package/dist/dts/index.d.ts +8 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/index.docs.d.ts +10 -0
- package/dist/dts/index.docs.d.ts.map +1 -0
- package/dist/dts/internal/helpers/parallel-limit.d.ts +9 -0
- package/dist/dts/internal/helpers/parallel-limit.d.ts.map +1 -0
- package/dist/dts/internal/helpers/sanitize-object.d.ts +11 -0
- package/dist/dts/internal/helpers/sanitize-object.d.ts.map +1 -0
- package/dist/dts/lib/context/cache.d.ts +149 -0
- package/dist/dts/lib/context/cache.d.ts.map +1 -0
- package/dist/dts/lib/context/index.d.ts +3 -0
- package/dist/dts/lib/context/index.d.ts.map +1 -0
- package/dist/dts/lib/context/integration-context.d.ts +16 -0
- package/dist/dts/lib/context/integration-context.d.ts.map +1 -0
- package/dist/dts/lib/errors/api-request-error.d.ts +10 -0
- package/dist/dts/lib/errors/api-request-error.d.ts.map +1 -0
- package/dist/dts/lib/errors/auth-request-error.d.ts +10 -0
- package/dist/dts/lib/errors/auth-request-error.d.ts.map +1 -0
- package/dist/dts/lib/errors/index.d.ts +8 -0
- package/dist/dts/lib/errors/index.d.ts.map +1 -0
- package/dist/dts/lib/errors/integration-error.d.ts +189 -0
- package/dist/dts/lib/errors/integration-error.d.ts.map +1 -0
- package/dist/dts/lib/errors/library-usage-error.d.ts +12 -0
- package/dist/dts/lib/errors/library-usage-error.d.ts.map +1 -0
- package/dist/dts/lib/errors/network-error.d.ts +11 -0
- package/dist/dts/lib/errors/network-error.d.ts.map +1 -0
- package/dist/dts/lib/errors/parse-error-to-readable-json.d.ts +7 -0
- package/dist/dts/lib/errors/parse-error-to-readable-json.d.ts.map +1 -0
- package/dist/dts/lib/errors/retry-request-error.d.ts +11 -0
- package/dist/dts/lib/errors/retry-request-error.d.ts.map +1 -0
- package/dist/dts/lib/index.d.ts +8 -0
- package/dist/dts/lib/index.d.ts.map +1 -0
- package/dist/dts/lib/index.docs.d.ts +10 -0
- package/dist/dts/lib/index.docs.d.ts.map +1 -0
- package/dist/dts/lib/internal/helpers/parallel-limit.d.ts +9 -0
- package/dist/dts/lib/internal/helpers/parallel-limit.d.ts.map +1 -0
- package/dist/dts/lib/internal/helpers/sanitize-object.d.ts +11 -0
- package/dist/dts/lib/internal/helpers/sanitize-object.d.ts.map +1 -0
- package/dist/dts/lib/logging/index.d.ts +2 -0
- package/dist/dts/lib/logging/index.d.ts.map +1 -0
- package/dist/dts/lib/logging/logger.d.ts +49 -0
- package/dist/dts/lib/logging/logger.d.ts.map +1 -0
- package/dist/dts/lib/requests/index.d.ts +3 -0
- package/dist/dts/lib/requests/index.d.ts.map +1 -0
- package/dist/dts/lib/requests/polarity-request.d.ts +411 -0
- package/dist/dts/lib/requests/polarity-request.d.ts.map +1 -0
- package/dist/dts/lib/requests/sanitize-request-options.d.ts +20 -0
- package/dist/dts/lib/requests/sanitize-request-options.d.ts.map +1 -0
- package/dist/dts/lib/testing/enhanced-utils/create-entity.d.ts +3 -0
- package/dist/dts/lib/testing/enhanced-utils/create-entity.d.ts.map +1 -0
- package/dist/dts/lib/testing/enhanced-utils/create-mock-integration-context.d.ts +3 -0
- package/dist/dts/lib/testing/enhanced-utils/create-mock-integration-context.d.ts.map +1 -0
- package/dist/dts/lib/testing/enhanced-utils/mock-request.d.ts +14 -0
- package/dist/dts/lib/testing/enhanced-utils/mock-request.d.ts.map +1 -0
- package/dist/dts/lib/testing/enhanced-utils/validate-integration.d.ts +8 -0
- package/dist/dts/lib/testing/enhanced-utils/validate-integration.d.ts.map +1 -0
- package/dist/dts/lib/testing/index.d.ts +6 -0
- package/dist/dts/lib/testing/index.d.ts.map +1 -0
- package/dist/dts/lib/testing/test-factory/create-integration-tests.d.ts +6 -0
- package/dist/dts/lib/testing/test-factory/create-integration-tests.d.ts.map +1 -0
- package/dist/dts/lib/testing/test-factory/test-do-lookup.d.ts +7 -0
- package/dist/dts/lib/testing/test-factory/test-do-lookup.d.ts.map +1 -0
- package/dist/dts/lib/testing/test-factory/test-on-message.d.ts +8 -0
- package/dist/dts/lib/testing/test-factory/test-on-message.d.ts.map +1 -0
- package/dist/dts/lib/types.d.ts +101 -0
- package/dist/dts/lib/types.d.ts.map +1 -0
- package/dist/dts/lib/zod-types.d.ts +278 -0
- package/dist/dts/lib/zod-types.d.ts.map +1 -0
- package/dist/dts/logging/index.d.ts +2 -0
- package/dist/dts/logging/index.d.ts.map +1 -0
- package/dist/dts/logging/logger.d.ts +49 -0
- package/dist/dts/logging/logger.d.ts.map +1 -0
- package/dist/dts/requests/index.d.ts +3 -0
- package/dist/dts/requests/index.d.ts.map +1 -0
- package/dist/dts/requests/polarity-request.d.ts +411 -0
- package/dist/dts/requests/polarity-request.d.ts.map +1 -0
- package/dist/dts/requests/sanitize-request-options.d.ts +20 -0
- package/dist/dts/requests/sanitize-request-options.d.ts.map +1 -0
- package/dist/dts/testing/enhanced-utils/create-entity.d.ts +3 -0
- package/dist/dts/testing/enhanced-utils/create-entity.d.ts.map +1 -0
- package/dist/dts/testing/enhanced-utils/create-mock-integration-context.d.ts +3 -0
- package/dist/dts/testing/enhanced-utils/create-mock-integration-context.d.ts.map +1 -0
- package/dist/dts/testing/enhanced-utils/mock-request.d.ts +14 -0
- package/dist/dts/testing/enhanced-utils/mock-request.d.ts.map +1 -0
- package/dist/dts/testing/enhanced-utils/validate-integration.d.ts +8 -0
- package/dist/dts/testing/enhanced-utils/validate-integration.d.ts.map +1 -0
- package/dist/dts/testing/index.d.ts +6 -0
- package/dist/dts/testing/index.d.ts.map +1 -0
- package/dist/dts/testing/test-factory/create-integration-tests.d.ts +6 -0
- package/dist/dts/testing/test-factory/create-integration-tests.d.ts.map +1 -0
- package/dist/dts/testing/test-factory/test-do-lookup.d.ts +7 -0
- package/dist/dts/testing/test-factory/test-do-lookup.d.ts.map +1 -0
- package/dist/dts/testing/test-factory/test-on-message.d.ts +8 -0
- package/dist/dts/testing/test-factory/test-on-message.d.ts.map +1 -0
- package/dist/dts/tsdoc-metadata.json +11 -0
- package/dist/dts/types.d.ts +101 -0
- package/dist/dts/types.d.ts.map +1 -0
- package/dist/dts/zod-types.d.ts +278 -0
- package/dist/dts/zod-types.d.ts.map +1 -0
- package/dist/es/lib/context/index.js +18 -0
- package/dist/es/lib/errors/api-request-error.js +15 -0
- package/dist/es/lib/errors/auth-request-error.js +15 -0
- package/dist/es/lib/errors/index.js +23 -0
- package/dist/es/lib/errors/integration-error.js +116 -0
- package/dist/es/lib/errors/library-usage-error.js +17 -0
- package/dist/es/lib/errors/network-error.js +88 -0
- package/dist/es/lib/errors/parse-error-to-readable-json.js +9 -0
- package/dist/es/lib/errors/retry-request-error.js +16 -0
- package/dist/es/lib/index.docs.js +25 -0
- package/dist/es/lib/index.js +50 -0
- package/dist/es/lib/internal/helpers/parallel-limit.js +36 -0
- package/dist/es/lib/internal/helpers/sanitize-object.js +37 -0
- package/dist/es/lib/logging/index.js +17 -0
- package/dist/es/lib/logging/logger.js +53 -0
- package/dist/es/lib/requests/index.js +18 -0
- package/dist/es/lib/requests/polarity-request.js +426 -0
- package/dist/es/lib/requests/sanitize-request-options.js +50 -0
- package/dist/es/lib/testing/enhanced-utils/create-entity.js +37 -0
- package/dist/es/lib/testing/enhanced-utils/create-mock-integration-context.js +36 -0
- package/dist/es/lib/testing/enhanced-utils/mock-request.js +22 -0
- package/dist/es/lib/testing/enhanced-utils/validate-integration.js +159 -0
- package/dist/es/lib/testing/index.js +21 -0
- package/dist/es/lib/testing/test-factory/create-integration-tests.js +53 -0
- package/dist/es/lib/testing/test-factory/test-do-lookup.js +24 -0
- package/dist/es/lib/testing/test-factory/test-on-message.js +24 -0
- package/dist/es/lib/types.js +5 -0
- package/dist/es/lib/zod-types.js +206 -0
- package/dist/lib/context/cache.js +2 -0
- package/dist/lib/context/index.js +18 -0
- package/dist/lib/context/integration-context.js +2 -0
- package/dist/lib/errors/api-request-error.js +15 -0
- package/dist/lib/errors/auth-request-error.js +15 -0
- package/dist/lib/errors/index.js +20 -8
- package/dist/lib/errors/integration-error.js +116 -0
- package/dist/lib/errors/library-usage-error.js +17 -0
- package/dist/lib/errors/network-error.js +88 -0
- package/dist/lib/errors/parse-error-to-readable-json.js +9 -0
- package/dist/lib/errors/retry-request-error.js +16 -0
- package/dist/lib/index.docs.js +25 -0
- package/dist/lib/index.js +47 -13
- package/dist/lib/internal/helpers/parallel-limit.js +36 -0
- package/dist/lib/internal/helpers/sanitize-object.js +37 -0
- package/dist/lib/logging/index.js +15 -2
- package/dist/lib/logging/logger.js +41 -5
- package/dist/lib/requests/index.js +15 -8
- package/dist/lib/requests/polarity-request.js +426 -0
- package/dist/lib/requests/sanitize-request-options.js +50 -0
- package/dist/lib/testing/enhanced-utils/create-entity.js +37 -0
- package/dist/lib/testing/enhanced-utils/create-mock-integration-context.js +36 -0
- package/dist/lib/testing/enhanced-utils/mock-request.js +22 -0
- package/dist/lib/testing/enhanced-utils/validate-integration.js +159 -0
- package/dist/lib/testing/index.js +21 -0
- package/dist/lib/testing/test-factory/create-integration-tests.js +53 -0
- package/dist/lib/testing/test-factory/test-do-lookup.js +24 -0
- package/dist/lib/testing/test-factory/test-on-message.js +24 -0
- package/dist/lib/types.js +5 -0
- package/dist/lib/zod-types.js +206 -0
- package/dist/polarity-integration-utils.d.ts +1259 -0
- package/package.json +81 -11
- package/dist/es/errors/RequestError.js +0 -12
- package/dist/es/errors/index.js +0 -11
- package/dist/es/errors/parseErrorToReadableJson.js +0 -4
- package/dist/es/helpers/async/index.js +0 -9
- package/dist/es/helpers/async/parallelLimit.js +0 -33
- package/dist/es/helpers/encodings/decodeBase64.js +0 -4
- package/dist/es/helpers/encodings/encodeBase64.js +0 -4
- package/dist/es/helpers/encodings/index.js +0 -11
- package/dist/es/helpers/index.js +0 -10
- package/dist/es/helpers/json/and.js +0 -4
- package/dist/es/helpers/json/filterObjectsContainingString.js +0 -10
- package/dist/es/helpers/json/index.js +0 -17
- package/dist/es/helpers/json/mapOverObject.js +0 -24
- package/dist/es/helpers/json/or.js +0 -4
- package/dist/es/helpers/json/transpose2dArray.js +0 -8
- package/dist/es/helpers/time/index.js +0 -11
- package/dist/es/helpers/time/millisecondsToHoursMinutesAndSeconds.js +0 -18
- package/dist/es/helpers/time/sleep.js +0 -13
- package/dist/es/index.js +0 -16
- package/dist/es/logging/index.js +0 -4
- package/dist/es/logging/logger.js +0 -17
- package/dist/es/requests/createRequestWithDefaults.js +0 -166
- package/dist/es/requests/createRequestsInParallel.js +0 -40
- package/dist/es/requests/index.js +0 -11
- package/dist/es/user-options/index.js +0 -9
- package/dist/es/user-options/validateUrlOption.js +0 -77
- package/dist/lib/errors/RequestError.js +0 -12
- package/dist/lib/errors/parseErrorToReadableJson.js +0 -4
- package/dist/lib/helpers/async/index.js +0 -9
- package/dist/lib/helpers/async/parallelLimit.js +0 -33
- package/dist/lib/helpers/encodings/decodeBase64.js +0 -4
- package/dist/lib/helpers/encodings/encodeBase64.js +0 -4
- package/dist/lib/helpers/encodings/index.js +0 -11
- package/dist/lib/helpers/index.js +0 -10
- package/dist/lib/helpers/json/and.js +0 -4
- package/dist/lib/helpers/json/filterObjectsContainingString.js +0 -10
- package/dist/lib/helpers/json/index.js +0 -17
- package/dist/lib/helpers/json/mapOverObject.js +0 -24
- package/dist/lib/helpers/json/or.js +0 -4
- package/dist/lib/helpers/json/transpose2dArray.js +0 -8
- package/dist/lib/helpers/time/index.js +0 -11
- package/dist/lib/helpers/time/millisecondsToHoursMinutesAndSeconds.js +0 -18
- package/dist/lib/helpers/time/sleep.js +0 -13
- package/dist/lib/requests/createRequestWithDefaults.js +0 -166
- package/dist/lib/requests/createRequestsInParallel.js +0 -40
- package/dist/lib/user-options/index.js +0 -9
- package/dist/lib/user-options/validateUrlOption.js +0 -77
- /package/dist/es/{requests/requestTypes.js → lib/context/cache.js} +0 -0
- /package/dist/{lib/requests/requestTypes.js → es/lib/context/integration-context.js} +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
36
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.types = exports.context = exports.logging = exports.requests = exports.errors = void 0;
|
|
40
|
+
const errors = __importStar(require("./errors"));
|
|
41
|
+
exports.errors = errors;
|
|
42
|
+
const requests = __importStar(require("./requests"));
|
|
43
|
+
exports.requests = requests;
|
|
44
|
+
const logging = __importStar(require("./logging"));
|
|
45
|
+
exports.logging = logging;
|
|
46
|
+
const context = __importStar(require("./context"));
|
|
47
|
+
exports.context = context;
|
|
48
|
+
const types = __importStar(require("./types"));
|
|
49
|
+
exports.types = types;
|
|
50
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parallelLimit = parallelLimit;
|
|
4
|
+
const errors_1 = require("../../errors");
|
|
5
|
+
/**
|
|
6
|
+
* Execute an array of async tasks while ensuring that no more than `limit`
|
|
7
|
+
* tasks are running at the same time. Results preserve task order.
|
|
8
|
+
*
|
|
9
|
+
* @param tasks - Array of thunked async tasks (`() => Promise<T>`).
|
|
10
|
+
* @param limit - Maximum number of concurrent tasks (positive integer).
|
|
11
|
+
*/
|
|
12
|
+
async function parallelLimit(tasks, limit) {
|
|
13
|
+
// ─── Validation ──────────────────────────────────────────────────────────────
|
|
14
|
+
if (!Array.isArray(tasks)) {
|
|
15
|
+
throw new errors_1.LibraryUsageError('parallelLimit: `tasks` must be an array');
|
|
16
|
+
}
|
|
17
|
+
if (tasks.length === 0)
|
|
18
|
+
return [];
|
|
19
|
+
if (typeof limit !== 'number' ||
|
|
20
|
+
!Number.isInteger(limit) ||
|
|
21
|
+
limit <= 0) {
|
|
22
|
+
throw new errors_1.LibraryUsageError('parallelLimit: `limit` must be a positive integer');
|
|
23
|
+
}
|
|
24
|
+
const results = new Array(tasks.length);
|
|
25
|
+
let next = 0;
|
|
26
|
+
async function worker() {
|
|
27
|
+
while (true) {
|
|
28
|
+
const current = next++;
|
|
29
|
+
if (current >= tasks.length)
|
|
30
|
+
break;
|
|
31
|
+
results[current] = await tasks[current]();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, () => worker()));
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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.sanitizeObject = sanitizeObject;
|
|
7
|
+
/** @internal */
|
|
8
|
+
const set_js_1 = __importDefault(require("lodash/set.js"));
|
|
9
|
+
const has_js_1 = __importDefault(require("lodash/has.js"));
|
|
10
|
+
/**
|
|
11
|
+
* Sanitizes the specified paths in an object by setting their values to a mask.
|
|
12
|
+
* This function returns a **new** object (deep clone) and does **not** mutate the original.
|
|
13
|
+
*
|
|
14
|
+
* @param obj - An object to sanitize (or nullish, which is returned directly).
|
|
15
|
+
* @param paths - An array of dot/bracket-notation paths to mask.
|
|
16
|
+
* @param mask - A replacement string. Defaults to "******".
|
|
17
|
+
* @returns A new object that has specified paths overwritten by `mask`.
|
|
18
|
+
*/
|
|
19
|
+
function sanitizeObject(obj, paths = [], mask = '******') {
|
|
20
|
+
// If not an object (null, undefined, etc.), return as-is.
|
|
21
|
+
if (!obj || typeof obj !== 'object') {
|
|
22
|
+
return obj;
|
|
23
|
+
}
|
|
24
|
+
// If paths is not a valid array, return as-is.
|
|
25
|
+
if (!Array.isArray(paths)) {
|
|
26
|
+
return obj;
|
|
27
|
+
}
|
|
28
|
+
// Create a deep clone so we do NOT mutate the original object
|
|
29
|
+
const clonedObj = structuredClone(obj);
|
|
30
|
+
// Replace each path's value with `mask`
|
|
31
|
+
for (const path of paths) {
|
|
32
|
+
if (typeof path === 'string' && (0, has_js_1.default)(clonedObj, path)) {
|
|
33
|
+
(0, set_js_1.default)(clonedObj, path, mask);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return clonedObj;
|
|
37
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./logger"), exports);
|
|
@@ -0,0 +1,53 @@
|
|
|
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 loggingLevels = ['info', 'debug', 'trace', 'warn', 'error', 'fatal'];
|
|
9
|
+
const writeToDevRunnerResults = (loggingLevel) => (...content) => fs_1.default.appendFileSync('devRunnerResults.json', '\n' + JSON.stringify({ SOURCE: `Logger.${loggingLevel}`, content }, null, 2));
|
|
10
|
+
const defaultLogger = loggingLevels.reduce((agg, level) => ({
|
|
11
|
+
...agg,
|
|
12
|
+
[level]: writeToDevRunnerResults(level)
|
|
13
|
+
}), {});
|
|
14
|
+
let _logger = defaultLogger;
|
|
15
|
+
/**
|
|
16
|
+
* Set the logger object used by the integration.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* Example of setting the logger within the integration's startup method:
|
|
20
|
+
* ```js
|
|
21
|
+
* const { setLogger } = require('polarity-integration-utils/logger');
|
|
22
|
+
*
|
|
23
|
+
* function startup(logger){
|
|
24
|
+
* setLogger(logger);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* You can now use {@link getLogger} to get the logger object anywhere within your integration codebase.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
* @param logger - the integration logger object passed into the `startup` method
|
|
32
|
+
*/
|
|
33
|
+
const setLogger = (logger) => {
|
|
34
|
+
_logger = logger;
|
|
35
|
+
};
|
|
36
|
+
exports.setLogger = setLogger;
|
|
37
|
+
/**
|
|
38
|
+
* return the logger object set via the {@link setLogger} method.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* Example of using the integration's logging object:
|
|
42
|
+
* ```js
|
|
43
|
+
* const { getLogger } = require('polarity-integration-utils/logger');
|
|
44
|
+
*
|
|
45
|
+
* const logger = getLogger();
|
|
46
|
+
* logger.trace('this is a trace message');
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @public
|
|
50
|
+
* @returns the integration's logger object
|
|
51
|
+
*/
|
|
52
|
+
const getLogger = () => _logger;
|
|
53
|
+
exports.getLogger = getLogger;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./polarity-request"), exports);
|
|
18
|
+
__exportStar(require("./sanitize-request-options"), exports);
|
|
@@ -0,0 +1,426 @@
|
|
|
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.PolarityRequest = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const util_1 = require("util");
|
|
9
|
+
const bottleneck_1 = __importDefault(require("bottleneck"));
|
|
10
|
+
const postman_request_1 = __importDefault(require("postman-request"));
|
|
11
|
+
const parallel_limit_1 = require("../internal/helpers/parallel-limit");
|
|
12
|
+
const node_util_1 = require("node:util");
|
|
13
|
+
const get_js_1 = __importDefault(require("lodash/get.js"));
|
|
14
|
+
const has_js_1 = __importDefault(require("lodash/has.js"));
|
|
15
|
+
const errors_1 = require("../errors");
|
|
16
|
+
const logging_1 = require("../logging");
|
|
17
|
+
const sanitize_request_options_1 = require("./sanitize-request-options");
|
|
18
|
+
/**
|
|
19
|
+
* A utility class for making HTTP requests
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
class PolarityRequest {
|
|
23
|
+
bottleneckLimiter;
|
|
24
|
+
/**
|
|
25
|
+
* Instance of a Bunyan logger
|
|
26
|
+
*/
|
|
27
|
+
logger;
|
|
28
|
+
internalThrottlingOptions;
|
|
29
|
+
/**
|
|
30
|
+
* postman-request library request object with default values set. Used internally for
|
|
31
|
+
* making HTTP requests directly via the postman-request library
|
|
32
|
+
*/
|
|
33
|
+
requestWithDefaults;
|
|
34
|
+
roundedSuccessStatusCodes = [200];
|
|
35
|
+
/**
|
|
36
|
+
* One or more HTTP response properties specified using JSON dot notation. If the
|
|
37
|
+
* specified path exists within the `body` property of the HTTP Response, an
|
|
38
|
+
* ApiRequestError will be thrown.
|
|
39
|
+
*
|
|
40
|
+
* By default, this value is an empty array and response properties are not used to
|
|
41
|
+
* detect errors.
|
|
42
|
+
* @defaultValue []
|
|
43
|
+
*/
|
|
44
|
+
httpResponseErrorProperties = [];
|
|
45
|
+
/**
|
|
46
|
+
* One or more HTTP response properties specified using JSON dot notation that
|
|
47
|
+
* point to an error message that should be displayed to the user in the event
|
|
48
|
+
* of an API error.
|
|
49
|
+
*
|
|
50
|
+
* The property should be a string value. If the property does not exist or is not
|
|
51
|
+
* a string value, a default error message will be used instead.
|
|
52
|
+
*/
|
|
53
|
+
httpResponseErrorMessageProperties = [];
|
|
54
|
+
/**
|
|
55
|
+
* Optional method that can be implemented to determine if an API error
|
|
56
|
+
* was encountered after an HTTP request is made.
|
|
57
|
+
*
|
|
58
|
+
* If the `isApiError` method is implemented
|
|
59
|
+
* the property `roundedSuccessStatusCodes` and `httpResponseErrorProperties` are not
|
|
60
|
+
* used to determine API errors.
|
|
61
|
+
*
|
|
62
|
+
* @returns An object indicating whether an API error was encountered and an optional message.
|
|
63
|
+
*/
|
|
64
|
+
isApiError = null;
|
|
65
|
+
/**
|
|
66
|
+
* An array of JSON dot notation paths to omit from the request options when logging.
|
|
67
|
+
*
|
|
68
|
+
* This property can be used to sanitize sensitive request properties that should not
|
|
69
|
+
* appear in logging.
|
|
70
|
+
*
|
|
71
|
+
* Note that the `requestOptions` object is automatically sanitized to remove properties that
|
|
72
|
+
* typically contain sensitive API key and passwords. For a list of properties that are
|
|
73
|
+
* automatically sanitized, see the {@link sanitizeRequestOptions} method.
|
|
74
|
+
*/
|
|
75
|
+
requestOptionsToSanitize = [];
|
|
76
|
+
userOptions = null;
|
|
77
|
+
/**
|
|
78
|
+
* Optional middleware method for modifying {@link HttpRequestOptions} before a request is made
|
|
79
|
+
* via the {@link PolarityRequest.run} method or {@link PolarityRequest.runInParallel} method.
|
|
80
|
+
* The returned `requestOptions` object will be used for the request. This method is passed
|
|
81
|
+
* a copy of the original `requestOptions` object so it can be modified without side effects.
|
|
82
|
+
*
|
|
83
|
+
* This method is typically used for adding authentication (e.g., auth headers, or basic auth) to every request.
|
|
84
|
+
* It can also be used to add headers that are required on every request or conditionally add headers based
|
|
85
|
+
* on the passed in `userOptions`.
|
|
86
|
+
*
|
|
87
|
+
* This method can be set as part of the {@link PolarityRequestOptions} when creating a new instance of the
|
|
88
|
+
* {@link PolarityRequest} class or can be set after the fact.
|
|
89
|
+
*
|
|
90
|
+
* @param requestOptions - A copy of the request options used for the request. This object can be modified
|
|
91
|
+
* without side effects.
|
|
92
|
+
* @param userOptions - The user options passed into the `doLookup` method.
|
|
93
|
+
* @returns The modified request options to use for the request.
|
|
94
|
+
*/
|
|
95
|
+
preprocessRequestOptions = async (requestOptions,
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
97
|
+
userOptions) => requestOptions;
|
|
98
|
+
/**
|
|
99
|
+
* Optional middleware method for modifying the {@link HttpRequestResponse} after a successful request.
|
|
100
|
+
* The passed in {@link HttpRequestResponse} object is not a copy but can be safely modified without
|
|
101
|
+
* side effects. The returned `HttpRequestResponse` object will be used for the response.
|
|
102
|
+
*
|
|
103
|
+
* @param response - The HTTP response from the request.
|
|
104
|
+
* @param requestOptions - The request options used for the request.
|
|
105
|
+
* @param userOptions - The user options passed into the `doLookup` method.
|
|
106
|
+
*/
|
|
107
|
+
postprocessRequestSuccess = async (response,
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
109
|
+
requestOptions,
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
111
|
+
userOptions) => response;
|
|
112
|
+
/**
|
|
113
|
+
* Method that can be implemented to post-process the HTTP response after a failed request.
|
|
114
|
+
* This method is typically used to inspect the error thrown and either alter the error
|
|
115
|
+
* object (e.g., to change the error message property to something more specific), to ignore
|
|
116
|
+
* the error (by not rethrowing it), or to take a specific action based on the error (e.g.,
|
|
117
|
+
* in the case of a RetryRequestError you may want to retry the request or return a special
|
|
118
|
+
* payload to the integration front end).
|
|
119
|
+
*
|
|
120
|
+
* @param error - The error thrown during the request.
|
|
121
|
+
* @param requestOptions - The request options used for the request.
|
|
122
|
+
* @param userOptions - The user options passed into the `doLookup` method.
|
|
123
|
+
*/
|
|
124
|
+
postprocessRequestFailure = (error,
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
126
|
+
requestOptions,
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
128
|
+
userOptions) => {
|
|
129
|
+
throw error;
|
|
130
|
+
};
|
|
131
|
+
get throttlingOptions() {
|
|
132
|
+
return this.internalThrottlingOptions;
|
|
133
|
+
}
|
|
134
|
+
// REVIEW: Do we want to tie our throttling specifically to Bottleneck or do we want to make
|
|
135
|
+
// it more generic and independent of Bottleneck?
|
|
136
|
+
set throttlingOptions(throttlingOptions) {
|
|
137
|
+
if ((0, node_util_1.isDeepStrictEqual)(this.internalThrottlingOptions, throttlingOptions))
|
|
138
|
+
return;
|
|
139
|
+
this.bottleneckLimiter = new bottleneck_1.default({
|
|
140
|
+
...throttlingOptions,
|
|
141
|
+
maxConcurrent: typeof throttlingOptions.maxConcurrent === 'string'
|
|
142
|
+
? Number.parseInt(throttlingOptions.maxConcurrent, 10)
|
|
143
|
+
: throttlingOptions.maxConcurrent,
|
|
144
|
+
minTime: typeof throttlingOptions.minTime === 'string'
|
|
145
|
+
? Number.parseInt(throttlingOptions.minTime, 10)
|
|
146
|
+
: throttlingOptions.minTime,
|
|
147
|
+
highWater: throttlingOptions.highWater || 50,
|
|
148
|
+
strategy: throttlingOptions.strategy || bottleneck_1.default.strategy.OVERFLOW
|
|
149
|
+
});
|
|
150
|
+
this.internalThrottlingOptions = throttlingOptions;
|
|
151
|
+
}
|
|
152
|
+
constructor(options = {}) {
|
|
153
|
+
const defaults = options.defaults || {};
|
|
154
|
+
const { ca, cert, key, passphrase, proxy, rejectUnauthorized = true, json = true } = defaults;
|
|
155
|
+
if ((0, logging_1.getLogger)().child) {
|
|
156
|
+
this.logger = (0, logging_1.getLogger)().child({
|
|
157
|
+
lib: 'polarity-integration-utils',
|
|
158
|
+
module: 'PolarityRequest'
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.logger = (0, logging_1.getLogger)();
|
|
163
|
+
}
|
|
164
|
+
if (options.isApiError) {
|
|
165
|
+
this.isApiError = options.isApiError;
|
|
166
|
+
}
|
|
167
|
+
if (options.roundedSuccessStatusCodes) {
|
|
168
|
+
this.roundedSuccessStatusCodes = options.roundedSuccessStatusCodes;
|
|
169
|
+
}
|
|
170
|
+
if (options.httpResponseErrorMessageProperties) {
|
|
171
|
+
this.httpResponseErrorMessageProperties =
|
|
172
|
+
options.httpResponseErrorMessageProperties;
|
|
173
|
+
}
|
|
174
|
+
if (options.httpResponseErrorProperties) {
|
|
175
|
+
this.httpResponseErrorProperties = options.httpResponseErrorProperties;
|
|
176
|
+
}
|
|
177
|
+
if (options.requestOptionsToSanitize) {
|
|
178
|
+
this.requestOptionsToSanitize = options.requestOptionsToSanitize;
|
|
179
|
+
}
|
|
180
|
+
if (options.postprocessRequestFailure) {
|
|
181
|
+
this.postprocessRequestFailure = options.postprocessRequestFailure;
|
|
182
|
+
}
|
|
183
|
+
if (options.postprocessRequestSuccess) {
|
|
184
|
+
this.postprocessRequestSuccess = options.postprocessRequestSuccess;
|
|
185
|
+
}
|
|
186
|
+
if (options.preprocessRequestOptions) {
|
|
187
|
+
this.preprocessRequestOptions = options.preprocessRequestOptions;
|
|
188
|
+
}
|
|
189
|
+
if (options.throttlingOptions) {
|
|
190
|
+
this.throttlingOptions = options.throttlingOptions;
|
|
191
|
+
}
|
|
192
|
+
const defaultRequestOptions = {
|
|
193
|
+
...(this.configFieldIsValid(ca) && { ca: fs_1.default.readFileSync(ca) }),
|
|
194
|
+
...(this.configFieldIsValid(cert) && { cert: fs_1.default.readFileSync(cert) }),
|
|
195
|
+
...(this.configFieldIsValid(key) && { key: fs_1.default.readFileSync(key) }),
|
|
196
|
+
...(this.configFieldIsValid(passphrase) && { passphrase }),
|
|
197
|
+
...(this.configFieldIsValid(proxy) && { proxy }),
|
|
198
|
+
...(typeof rejectUnauthorized === 'boolean' && { rejectUnauthorized }),
|
|
199
|
+
json
|
|
200
|
+
};
|
|
201
|
+
this.requestWithDefaults = (0, util_1.promisify)(postman_request_1.default.defaults(defaultRequestOptions));
|
|
202
|
+
}
|
|
203
|
+
configFieldIsValid = (field) => typeof field === 'string' && field.length > 0;
|
|
204
|
+
/**
|
|
205
|
+
* Makes a single HTTP request and returns the response or throws an error
|
|
206
|
+
*
|
|
207
|
+
* @param requestOptions - request options used to make the HTTP request
|
|
208
|
+
* @returns The HTTP response
|
|
209
|
+
*/
|
|
210
|
+
async run(requestOptions) {
|
|
211
|
+
if (!this.userOptions) {
|
|
212
|
+
throw new errors_1.LibraryUsageError('PolarityRequest property `userOptions` must be set before calling `run` method');
|
|
213
|
+
}
|
|
214
|
+
// Note that we specifically pass a copy of requestOptions to `preprocessRequestOptions`
|
|
215
|
+
// which lets the user modify the requestOptions object without affecting the original
|
|
216
|
+
const postprocessedRequestOptions = await this.preprocessRequestOptions({
|
|
217
|
+
...requestOptions
|
|
218
|
+
}, this.userOptions);
|
|
219
|
+
let postprocessRequestResults;
|
|
220
|
+
try {
|
|
221
|
+
const httpResponse = await (this.bottleneckLimiter
|
|
222
|
+
? this.bottleneckLimiter.schedule(this.requestWithDefaults, postprocessedRequestOptions)
|
|
223
|
+
: this.requestWithDefaults(postprocessedRequestOptions));
|
|
224
|
+
if (this.bottleneckLimiter) {
|
|
225
|
+
this.logger.trace({ httpResponse }, 'HTTP Response via Bottleneck');
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
this.logger.trace({ httpResponse }, 'HTTP Response');
|
|
229
|
+
}
|
|
230
|
+
this.maybeThrowApiRequestError(httpResponse, postprocessedRequestOptions);
|
|
231
|
+
postprocessRequestResults = await this.postprocessRequestSuccess(httpResponse, postprocessedRequestOptions, this.userOptions);
|
|
232
|
+
}
|
|
233
|
+
catch (requestError) {
|
|
234
|
+
let transformedError = requestError;
|
|
235
|
+
if (requestError instanceof errors_1.LibraryUsageError) {
|
|
236
|
+
throw requestError;
|
|
237
|
+
}
|
|
238
|
+
if (!(requestError instanceof errors_1.ApiRequestError)) {
|
|
239
|
+
transformedError = new errors_1.NetworkError('Network error encountered during request', {
|
|
240
|
+
cause: requestError,
|
|
241
|
+
requestOptions: postprocessedRequestOptions,
|
|
242
|
+
requestOptionsToSanitize: this.requestOptionsToSanitize
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
if (requestError instanceof bottleneck_1.default.BottleneckError) {
|
|
246
|
+
transformedError = new errors_1.RetryRequestError('This request has been dropped for going over Integration Configured API Throttling Limits', {
|
|
247
|
+
requestOptions: postprocessedRequestOptions,
|
|
248
|
+
requestOptionsToSanitize: this.requestOptionsToSanitize
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
// Possibly throws an error
|
|
252
|
+
await this.postprocessRequestFailure(transformedError, postprocessedRequestOptions, this.userOptions);
|
|
253
|
+
}
|
|
254
|
+
return postprocessRequestResults;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Checks whether the HTTP response is an API error and throws an ApiRequestError if it is.
|
|
258
|
+
*
|
|
259
|
+
* @param httpResponse - The HTTP response from the Postman request.
|
|
260
|
+
* @param requestOptions - The options used for the request.
|
|
261
|
+
*
|
|
262
|
+
* @throws {@link ApiRequestError}
|
|
263
|
+
* Throws an error if the response indicates an API error.
|
|
264
|
+
*/
|
|
265
|
+
maybeThrowApiRequestError(httpResponse, requestOptions) {
|
|
266
|
+
const { statusCode, body } = httpResponse;
|
|
267
|
+
const requestOptionsWithoutSensitiveData = (0, sanitize_request_options_1.sanitizeRequestOptions)(requestOptions, this.requestOptionsToSanitize);
|
|
268
|
+
this.logger.trace({
|
|
269
|
+
requestOptions: requestOptionsWithoutSensitiveData,
|
|
270
|
+
statusCode,
|
|
271
|
+
responseBody: body
|
|
272
|
+
}, 'Request ran, checking for status error');
|
|
273
|
+
let hasApiError;
|
|
274
|
+
let message;
|
|
275
|
+
if (this.isApiError) {
|
|
276
|
+
const result = this.isApiError(httpResponse, requestOptions, this.userOptions);
|
|
277
|
+
if (!result || typeof result.isApiError !== 'boolean') {
|
|
278
|
+
throw new errors_1.LibraryUsageError('PolarityRequest property `isApiError` must return an object containing an `isApiError` property with a boolean value. It can also optionally include a `message` property with a custom error message.');
|
|
279
|
+
}
|
|
280
|
+
hasApiError = result.isApiError;
|
|
281
|
+
message = result.message
|
|
282
|
+
? result.message
|
|
283
|
+
: this.getErrorMessageFromHttpResponse(body, 'Unexpected Error HTTP Response Received');
|
|
284
|
+
}
|
|
285
|
+
else if (this.isHttpStatusCodeError(statusCode)) {
|
|
286
|
+
hasApiError = true;
|
|
287
|
+
message = this.getErrorMessageFromHttpResponse(body, `Unexpected HTTP Status Code ${statusCode} Received`);
|
|
288
|
+
}
|
|
289
|
+
else if (this.hasHttpResponseErrorProperty(body)) {
|
|
290
|
+
hasApiError = true;
|
|
291
|
+
message = this.getErrorMessageFromHttpResponse(body, 'Unexpected Error HTTP Response Received');
|
|
292
|
+
}
|
|
293
|
+
if (hasApiError) {
|
|
294
|
+
throw new errors_1.ApiRequestError(message, {
|
|
295
|
+
status: statusCode.toString(),
|
|
296
|
+
requestOptions: requestOptionsWithoutSensitiveData,
|
|
297
|
+
requestOptionsToSanitize: this.requestOptionsToSanitize,
|
|
298
|
+
meta: {
|
|
299
|
+
body
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Returns true if the `httpStatusCode` is not one of the rounded HTTP status codes
|
|
306
|
+
* specified in the PolarityRequest `roundedSuccessStatusCodes` property.
|
|
307
|
+
*
|
|
308
|
+
* @param httpStatusCode - A numeric HTTP Status Code
|
|
309
|
+
* @returns true if the provided `httpStatusCode` is an error code
|
|
310
|
+
*/
|
|
311
|
+
isHttpStatusCodeError(httpStatusCode) {
|
|
312
|
+
const roundedStatus = Math.round(httpStatusCode / 100) * 100;
|
|
313
|
+
const statusCodeNotSuccessful = !this.roundedSuccessStatusCodes.includes(roundedStatus);
|
|
314
|
+
return statusCodeNotSuccessful;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Returns true indicating that the API returned an error if the `httpBody` contains
|
|
318
|
+
* one of the paths specified by the PolarityRequest `httpResponseErrorProperties`
|
|
319
|
+
* property.
|
|
320
|
+
*
|
|
321
|
+
* @param httpBody - body property from the HttpRequestResponse
|
|
322
|
+
* @returns `true` if the httpBody property contains properties specified in `httpResponseErrorProperties`
|
|
323
|
+
*/
|
|
324
|
+
hasHttpResponseErrorProperty(httpBody) {
|
|
325
|
+
return this.httpResponseErrorProperties.some((property) => (0, has_js_1.default)(httpBody, property));
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Returns an error message based on the `httpResponseErrorMessageProperties` first. If no
|
|
329
|
+
* message is found, it then uses the `httpResponseErrorProperties` to attempt to find
|
|
330
|
+
* a suitable error message. If no message is still found, the `defaultMessage` is returned.
|
|
331
|
+
*
|
|
332
|
+
* @param httpBody - JSON Object returned by an HTTP Request
|
|
333
|
+
* @param defaultMessage - A default error message to use if no specific error messages are found
|
|
334
|
+
* @returns An error message
|
|
335
|
+
*/
|
|
336
|
+
getErrorMessageFromHttpResponse(httpBody, defaultMessage) {
|
|
337
|
+
let message = this.maybeGetStringPropertyValue(httpBody, this.httpResponseErrorMessageProperties);
|
|
338
|
+
if (!message) {
|
|
339
|
+
message = this.maybeGetStringPropertyValue(httpBody, this.httpResponseErrorProperties);
|
|
340
|
+
}
|
|
341
|
+
return message ? message : defaultMessage;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Given a list of `properties` which are strings representing JSON dot notation, this
|
|
345
|
+
* method returns the first string property found at the given JSON path
|
|
346
|
+
* in the given `object`.
|
|
347
|
+
*
|
|
348
|
+
* @param object - An object to find properties in
|
|
349
|
+
* @param properties - a list of JSON dot notation properties to look for within `object`
|
|
350
|
+
* @returns A string value of the property found within the given object or undefined if no value is found
|
|
351
|
+
*/
|
|
352
|
+
maybeGetStringPropertyValue(object, properties) {
|
|
353
|
+
let message;
|
|
354
|
+
properties.some((property) => {
|
|
355
|
+
if ((0, has_js_1.default)(object, property)) {
|
|
356
|
+
const propertyValue = (0, get_js_1.default)(object, property);
|
|
357
|
+
if (typeof propertyValue === 'string') {
|
|
358
|
+
message = propertyValue;
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
return message;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Runs multiple requests in parallel with a limit on the maximum number of concurrent requests.
|
|
367
|
+
*
|
|
368
|
+
* When running multiple request at once it is often useful to be able to tie a specific request
|
|
369
|
+
* back to the entity the request is for. To support this, the `HttpRequestOptions` object accepts
|
|
370
|
+
* an optional `entity` property which can be assigned to the Entity the request is being made for.
|
|
371
|
+
* The `HttpRequestResponse` object returned by this method will include the same `entity` property
|
|
372
|
+
* making it easy to match the response to the entity.
|
|
373
|
+
*
|
|
374
|
+
* Alternatively, for requests that are made for multiple entities at once (e.g., a query that can
|
|
375
|
+
* search multiple entities at a time), the `HttpRequestOptions` object also has an `entities`
|
|
376
|
+
* property which accept an array of entity objects. Similar to the `entity`, the
|
|
377
|
+
* `entities` property will be set on the `HttpRequestResponse` object.
|
|
378
|
+
*
|
|
379
|
+
* Finally, if you are looking to pass through a custom request id you can do that using the
|
|
380
|
+
* `requestId` property.
|
|
381
|
+
*
|
|
382
|
+
* @param options - An array of request options for running requests in parallel.
|
|
383
|
+
* @returns A promise that resolves to an array of responses. If the `returnErrors` property is set to `true`
|
|
384
|
+
* then the response objects will have their `error` property set to the thrown error.
|
|
385
|
+
*/
|
|
386
|
+
async runInParallel(options) {
|
|
387
|
+
const allRequestOptions = options.allRequestOptions;
|
|
388
|
+
const returnErrors = options.returnErrors || false;
|
|
389
|
+
const maxConcurrentRequests = options.maxConcurrentRequests || 5;
|
|
390
|
+
if (!Array.isArray(allRequestOptions)) {
|
|
391
|
+
throw new errors_1.LibraryUsageError('Invalid or missing option for PolarityRequest.runInParallel(): `allRequestOptions` is a required option and must be an array of `HttpRequestOptions` with at least one `HttpRequestOptions` object in it.');
|
|
392
|
+
}
|
|
393
|
+
// REVIEW: We're currently supporting tying the entity to the request by using
|
|
394
|
+
// the `entity` property, the `entities` property, or the generic `requestId` property.
|
|
395
|
+
const tasks = allRequestOptions.map((requestOptions) => {
|
|
396
|
+
return async () => {
|
|
397
|
+
try {
|
|
398
|
+
const response = await this.run(requestOptions);
|
|
399
|
+
if (requestOptions.entity) {
|
|
400
|
+
response.entity = requestOptions.entity;
|
|
401
|
+
}
|
|
402
|
+
else if (requestOptions.entities) {
|
|
403
|
+
response.entities = requestOptions.entities;
|
|
404
|
+
}
|
|
405
|
+
else if (requestOptions.requestId) {
|
|
406
|
+
response.requestId = requestOptions.requestId;
|
|
407
|
+
}
|
|
408
|
+
return response;
|
|
409
|
+
}
|
|
410
|
+
catch (requestError) {
|
|
411
|
+
if (returnErrors) {
|
|
412
|
+
return {
|
|
413
|
+
error: requestError
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
throw requestError;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
});
|
|
422
|
+
const results = await (0, parallel_limit_1.parallelLimit)(tasks, maxConcurrentRequests);
|
|
423
|
+
return results;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
exports.PolarityRequest = PolarityRequest;
|