try-typescript
Advanced tools
Comparing version
export declare class Try<T> { | ||
private value; | ||
private executionStack; | ||
private errorStack?; | ||
private internalError?; | ||
private constructor(); | ||
static combine<T extends any[], R>(...args: [...{ | ||
[K in keyof T]: Try<T[K]>; | ||
}, (...values: T) => R]): Try<R>; | ||
static success<T>(value: T): Try<T>; | ||
@@ -11,3 +14,3 @@ static failure<T>(error: Error): Try<T>; | ||
private setError; | ||
private runElement; | ||
private executeElement; | ||
private runExecutionStack; | ||
@@ -14,0 +17,0 @@ run(): Promise<Try<T>>; |
@@ -16,2 +16,3 @@ "use strict"; | ||
OF: "OF", | ||
COMBINE: 'COMBINE', | ||
MAP: 'MAP', | ||
@@ -34,2 +35,11 @@ ANDTHEN: 'ANDTHEN', | ||
} | ||
static combine(...args) { | ||
const trys = args.slice(0, -1); | ||
const func = args[args.length - 1]; | ||
return new Try({ | ||
name: TryFunctions.COMBINE, | ||
functionData: { func: () => func(...trys.map(tryObj => tryObj.value)), trys }, | ||
returning: true | ||
}); | ||
} | ||
//Static methods to create a Try object | ||
@@ -55,21 +65,13 @@ static success(value) { | ||
setError(err) { | ||
this.errorStack = err; | ||
this.internalError = err; | ||
return this; | ||
} | ||
runElement(executionElement_1) { | ||
return __awaiter(this, arguments, void 0, function* (executionElement, isFirst = false) { | ||
try { | ||
if (isFirst && executionElement.returning) { | ||
this.value = yield executionElement.functionData.func(); | ||
return; | ||
} | ||
if (executionElement.returning) { | ||
this.value = yield executionElement.functionData.func(this.value); | ||
return; | ||
} | ||
yield executionElement.functionData.func(this.value); | ||
executeElement(executionElement) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (executionElement.returning) { | ||
return this.value = executionElement.name === TryFunctions.OF | ||
? yield executionElement.functionData.func() | ||
: yield executionElement.functionData.func(this.value); | ||
} | ||
catch (e) { | ||
this.errorStack = e; | ||
} | ||
yield executionElement.functionData.func(this.value); | ||
}); | ||
@@ -79,78 +81,73 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
for (let i = 0; i < this.executionStack.length; i++) { | ||
const executionElement = this.executionStack[i]; | ||
for (const executionElement of this.executionStack) { | ||
try { | ||
switch (executionElement.name) { | ||
case TryFunctions.MAP: { | ||
if (this.isSuccess()) | ||
yield this.runElement(executionElement, executionElement.name === TryFunctions.OF); | ||
break; | ||
if (executionElement.name === TryFunctions.MAP) { | ||
if (this.isSuccess()) | ||
yield this.executeElement(executionElement); | ||
} | ||
else if (executionElement.name === TryFunctions.FLATMAP) { | ||
if (this.isSuccess()) { | ||
const tryObject = yield executionElement.functionData.func(this.value); | ||
this.value = yield tryObject.get(); | ||
} | ||
case TryFunctions.FLATMAP: { | ||
if (this.isSuccess()) { | ||
const tryObject = yield executionElement.functionData.func(this.value); | ||
this.value = yield tryObject.get(); | ||
} | ||
else if (executionElement.name === TryFunctions.ANDTHEN) { | ||
if (this.isSuccess()) | ||
yield this.executeElement(executionElement); | ||
} | ||
else if (executionElement.name === TryFunctions.FILTER) { | ||
if (this.isSuccess()) { | ||
if (!(yield executionElement.functionData.func(this.value))) { | ||
yield executionElement.functionData.fallbackFunction(this.value); | ||
} | ||
break; | ||
} | ||
case TryFunctions.ANDTHEN: { | ||
if (this.isSuccess()) | ||
yield this.runElement(executionElement, executionElement.name === TryFunctions.OF); | ||
break; | ||
} | ||
case TryFunctions.FILTER: { | ||
if (this.isSuccess()) { | ||
if (!(yield executionElement.functionData.func(this.value))) { | ||
yield executionElement.functionData.fallbackFunction(this.value); | ||
} | ||
} | ||
else if (executionElement.name === TryFunctions.FILTERNOT) { | ||
if (this.isSuccess()) { | ||
if (yield executionElement.functionData.func(this.value)) { | ||
yield executionElement.functionData.fallbackFunction(this.value); | ||
} | ||
break; | ||
} | ||
case TryFunctions.FILTERNOT: { | ||
if (this.isSuccess()) { | ||
if (yield executionElement.functionData.func(this.value)) { | ||
yield executionElement.functionData.fallbackFunction(this.value); | ||
} | ||
} | ||
break; | ||
} | ||
else if (executionElement.name === TryFunctions.PEEK) { | ||
if (this.isSuccess()) | ||
yield executionElement.functionData.func(this.value); | ||
} | ||
else if (executionElement.name === TryFunctions.RECOVER) { | ||
if (this.isFailure()) { | ||
this.internalError = undefined; | ||
this.value = yield executionElement.functionData.func(this.internalError); | ||
} | ||
case TryFunctions.PEEK: { | ||
if (this.isSuccess()) | ||
yield executionElement.functionData.func(this.value); | ||
break; | ||
} | ||
else if (executionElement.name === TryFunctions.RECOVERWITH) { | ||
if (this.isFailure()) { | ||
this.internalError = undefined; | ||
const tryObject = yield executionElement.functionData.func(this.internalError); | ||
this.value = yield tryObject.get(); | ||
} | ||
case TryFunctions.RECOVER: { | ||
if (this.isFailure()) { | ||
this.errorStack = undefined; | ||
this.value = yield executionElement.functionData.func(this.errorStack); | ||
} | ||
else if (executionElement.name === TryFunctions.ONSUCCESS) { | ||
if (this.isSuccess()) | ||
yield executionElement.functionData.func(this.value); | ||
} | ||
else if (executionElement.name === TryFunctions.ONFAILURE) { | ||
if (this.isFailure()) | ||
yield executionElement.functionData.func(this.internalError); | ||
} | ||
else if (executionElement.name === TryFunctions.COMBINE) { | ||
const values = yield Promise.all(executionElement.functionData.trys.map((tryObject) => __awaiter(this, void 0, void 0, function* () { return yield tryObject.run(); }))); | ||
for (const v of values) { | ||
if (v.isFailure()) { | ||
this.internalError = v.internalError; | ||
break; | ||
} | ||
break; | ||
} | ||
case TryFunctions.RECOVERWITH: { | ||
if (this.isFailure()) { | ||
this.errorStack = undefined; | ||
const tryObject = yield executionElement.functionData.func(this.errorStack); | ||
this.value = yield tryObject.get(); | ||
} | ||
break; | ||
} | ||
case TryFunctions.ONSUCCESS: { | ||
if (this.isSuccess()) | ||
yield executionElement.functionData.func(this.value); | ||
break; | ||
} | ||
case TryFunctions.ONFAILURE: { | ||
if (this.isFailure()) | ||
yield executionElement.functionData.func(this.errorStack); | ||
break; | ||
} | ||
default: { | ||
//This will typically run one of the static methods | ||
yield this.runElement(executionElement, executionElement.name === TryFunctions.OF); | ||
} | ||
this.value = yield executionElement.functionData.func(...values); | ||
} | ||
else { | ||
yield this.executeElement(executionElement); | ||
} | ||
} | ||
catch (ex) { | ||
// @ts-ignore | ||
this.errorStack = ex; | ||
this.internalError = ex; | ||
} | ||
@@ -171,3 +168,3 @@ } | ||
if (this.isFailure()) | ||
throw this.errorStack; | ||
throw this.internalError; | ||
return this.value; | ||
@@ -185,3 +182,3 @@ }); | ||
yield this.runExecutionStack(); | ||
return this.isFailure() ? yield fn(this.errorStack) : this.value; | ||
return this.isFailure() ? yield fn(this.internalError) : this.value; | ||
}); | ||
@@ -193,3 +190,3 @@ } | ||
if (this.isFailure()) | ||
throw fn(this.errorStack); | ||
throw fn(this.internalError); | ||
return this.value; | ||
@@ -263,6 +260,6 @@ }); | ||
isSuccess() { | ||
return this.errorStack === undefined; | ||
return this.internalError === undefined; | ||
} | ||
isFailure() { | ||
return this.errorStack !== undefined; | ||
return this.internalError !== undefined; | ||
} | ||
@@ -286,5 +283,5 @@ onSuccess(fn) { | ||
getCause() { | ||
return this.errorStack; | ||
return this.internalError; | ||
} | ||
} | ||
exports.Try = Try; |
@@ -197,2 +197,30 @@ "use strict"; | ||
}); | ||
describe("Try.combine", () => { | ||
test("combine should run all Try instances and pass the results to the provided function", () => __awaiter(void 0, void 0, void 0, function* () { | ||
const r = __1.Try.success(2); | ||
const r2 = __1.Try.success(3); | ||
const r3 = __1.Try.of(() => { | ||
if (0.6 > 0.5) | ||
return "3"; | ||
throw new Error("Random error"); | ||
}); | ||
const f = (a, b, c) => a + b + c; | ||
const r4 = __1.Try.combine(r, r2, r3, f); | ||
yield expect(r4.get()).resolves.toBe("53"); | ||
expect(r4.isSuccess()).toBe(true); | ||
})); | ||
test("combine should run all Try instances and results in Failure for the first instance that is a Failure", () => __awaiter(void 0, void 0, void 0, function* () { | ||
const r = __1.Try.success(2); | ||
const r2 = __1.Try.success(3); | ||
const r3 = __1.Try.of(() => { | ||
if (0.3 > 0.5) | ||
return "3"; | ||
throw new Error("Random error"); | ||
}); | ||
const f = (a, b, c) => a + b + c; | ||
const r4 = __1.Try.combine(r, r2, r3, f); | ||
yield expect(r4.get()).rejects.toThrow("Random error"); | ||
expect(r4.isFailure()).toBe(true); | ||
})); | ||
}); | ||
}); |
{ | ||
"name": "try-typescript", | ||
"version": "0.3.2", | ||
"version": "0.4.0", | ||
"description": "This repository implements a Try class inspired by the Vavr library in Java. The Try class is a functional programming construct for handling computations that may succeed or fail. It encapsulates exceptions and streamlines error handling, reducing boilerplate code and enhancing code readability. ", | ||
@@ -8,4 +8,3 @@ "main": "dist/index.js", | ||
"build": "tsc", | ||
"test": "jest --runInBand --detectOpenHandles", | ||
"start": "ts-node src/index.ts" | ||
"test": "jest --runInBand --detectOpenHandles" | ||
}, | ||
@@ -12,0 +11,0 @@ "repository": { |
@@ -33,3 +33,34 @@ # Try-Typescript | ||
``` | ||
<br> | ||
### `combine<T extends any[], R>(...args: [...{ [K in keyof T]: Try<T[K]> }, (...values: T) => R]): Try<R>` | ||
```typescript | ||
//All passed Try instances are successful | ||
const r = Try.success(2); | ||
const r2 = Try.success(3); | ||
const r3 = Try.of(() => { | ||
if(0.6 > 0.5) return "3"; | ||
throw new Error("Random error"); | ||
}); | ||
const f = (a: number, b: number, c: string) => a + b + c; | ||
const r4 = await Try.combine(r, r2, r3, f).get(); //=> "53" ; | ||
//One of the passed Try instances is a failure | ||
const r = Try.success(2); | ||
const r2 = Try.success(3); | ||
const r3 = Try.of(() => { | ||
if(0.3 > 0.5) return "3"; | ||
throw new Error("Random error"); | ||
}); //=> Is a Failure | ||
const f = (a: number, b: number, c: string) => a + b + c; | ||
const r4 = Try.combine(r, r2, r3, f); | ||
await r4.get(); //=> Will throw 'Random error' | ||
``` | ||
<br> | ||
@@ -36,0 +67,0 @@ |
40922
6.21%565
5.21%386
8.73%