@hypernetlabs/utils
Version:
Utilities used by Hypernet Labs packages
165 lines • 6.44 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResultUtils = void 0;
const delay_1 = __importDefault(require("delay"));
const neverthrow_1 = require("neverthrow");
class ResultUtils {
static combine(asyncResultList) {
return neverthrow_1.ResultAsync.fromPromise(Promise.all(asyncResultList), (e) => {
return e;
}).andThen(ResultUtils.combineResultList);
}
static combineResultList(resultList) {
return resultList.reduce((acc, result) => {
return acc.isOk()
? result.isErr()
? (0, neverthrow_1.err)(result.error)
: acc.map((values) => {
values.push(result.value);
return values;
})
: acc;
}, (0, neverthrow_1.ok)([]));
}
static race(asyncResultList) {
return neverthrow_1.ResultAsync.fromPromise(Promise.race(asyncResultList), (e) => {
return e;
}).andThen(ResultUtils.resultRace);
}
static resultRace(result) {
return result.isErr() ? (0, neverthrow_1.err)(result.error) : (0, neverthrow_1.ok)(result.value);
}
static fromThrowableResult(throwableCallback) {
const throwable = neverthrow_1.Result.fromThrowable(throwableCallback, (err) => {
return err;
});
return throwable();
}
static executeSerially(funcList) {
// const results = new Array<T>();
// // for (const func of funcList) {
// // func().map((val) => {})
// // }
// try {
// funcList.reduce(
// (p: ResultAsync<void, E>, x) =>
// p.andThen(_ => {
// return x()
// .map((result) => {
// results.push(result);
// })
// .mapErr((e) => {
// throw e;
// });
// }),
// okAsync<void, E>(undefined)
// );
// }
// catch (e) {
// return errAsync(e);
// }
const func = async () => {
const results = new Array();
for (const func of funcList) {
const result = await func();
if (result.isErr()) {
throw result.error;
}
else {
results.push(result.value);
}
}
return results;
};
return neverthrow_1.ResultAsync.fromPromise(func(), (e) => {
return e;
});
}
static backoffAndRetry(func, acceptableErrors, maxAttempts, baseSeconds = 5) {
if (maxAttempts != null && maxAttempts < 1) {
throw new Error("maxAttempts must be 1 or more!");
}
if (baseSeconds < 1) {
throw new Error("baseSeconds must be 1 or more!");
}
const runAndCheck = (currentAttempt, nextAttemptSecs, lastError) => {
if (maxAttempts != null && currentAttempt > maxAttempts) {
if (lastError == null) {
throw new Error("Error before first function run; logical error! maxAttempts must be 1 or more!");
}
return (0, neverthrow_1.errAsync)(lastError);
}
// Check the result. If it's not an error, we're done!
// If it's an error, check the error type against acceptableErrors. If it's in the list,
// wait some amount of time and try again.
// If it is not in the list, return the error and stop.
return func().orElse((e) => {
let retry = false;
for (const acceptableError of acceptableErrors) {
if (e instanceof acceptableError) {
retry = true;
break;
}
}
if (retry) {
return neverthrow_1.ResultAsync.fromSafePromise((0, delay_1.default)(nextAttemptSecs)).andThen(() => {
return runAndCheck(++currentAttempt, nextAttemptSecs * 2, e);
});
}
return (0, neverthrow_1.errAsync)(e);
});
};
return runAndCheck(1, baseSeconds, null);
}
/**
* filter() is a normal filter method that works with async callbacks.
* This works like a nomral array filter() call, except the callback returns
* a ResultAsync<boolean> instead of just boolean.
* @param arr the source array
* @param callback a function that returns a ResultAsync<boolean>; if it returns true then the source value is included in the result.
* @returns a ResultAsync containing an array of source values where the callback returns true.
*/
static filter(arr, callback) {
const filterVals = new Array();
return ResultUtils.combine(arr.map((val) => {
return callback(val).map((result) => {
if (result) {
filterVals.push(val);
}
});
})).map(() => {
return filterVals;
});
}
/**
* map() is a way to combine multiple async callbacks.
* This works like a normal array map() call, except the callbacks return ResultAsync.
* It will combine all the results and return a single ResultAsync with an array of the mapped
* values.
* @param arr The source array of objects
* @param callback A function that returns a ResultAsync and a value
* @returns A ResultAsync containing an array of the mapped values or the first error.
*/
static map(arr, callback) {
const mapVals = new Array();
return ResultUtils.combine(arr.map((val) => {
return callback(val).map((result) => {
mapVals.push(result);
});
})).map(() => {
return mapVals;
});
}
static delay(ms) {
return neverthrow_1.ResultAsync.fromSafePromise(new Promise((resolve) => {
setTimeout(() => {
resolve();
}, ms);
}));
}
}
exports.ResultUtils = ResultUtils;
//# sourceMappingURL=ResultUtils.js.map