- commit
- db23e0e
- parent
- a525a64
- author
- Eric Bower
- date
- 2023-04-20 01:42:59 +0000 UTC
refactor: `call` returns `Result` now
5 files changed,
+119,
-54
+36,
-0
1@@ -0,0 +1,36 @@
2+import { safe } from "./fx/mod.ts";
3+
4+interface Middleware<Ctx> {}
5+type Next = () => void;
6+interface PipeCtx {}
7+
8+export function compose<Ctx extends PipeCtx = PipeCtx>(
9+ middleware: Middleware<Ctx>[],
10+) {
11+ if (!Array.isArray(middleware)) {
12+ throw new TypeError("Middleware stack must be an array!");
13+ }
14+
15+ for (const fn of middleware) {
16+ if (typeof fn !== "function") {
17+ throw new TypeError("Middleware must be composed of functions!");
18+ }
19+ }
20+
21+ return function* composeFn(context: Ctx, next?: Next): SagaIterator<void> {
22+ // last called middleware #
23+ let index = -1;
24+ yield* safe(() => dispatch(0));
25+
26+ function* dispatch(i: number) {
27+ if (i <= index) {
28+ throw new Error("next() called multiple times");
29+ }
30+ index = i;
31+ let fn: any = middleware[i];
32+ if (i === middleware.length) fn = next;
33+ if (!fn) return;
34+ yield* safe(() => fn(context, dispatch.bind(null, i + 1)));
35+ }
36+ };
37+}
+14,
-15
1@@ -24,28 +24,16 @@ export function* toOperation<T>(opFn: OpFn<T>): Operation<T> {
2 return result;
3 }
4
5-export function call<T>(op: OpFn<T>): Operation<T> {
6+export function unsafeCall<T>(op: OpFn<T>): Operation<T> {
7 return action(function* (resolve) {
8 const result = yield* toOperation(op);
9 resolve(result);
10 });
11 }
12
13-export function* go<T>(op: OpFn<T>): Operation<Task<Result<T>>> {
14- return yield* spawn(function* () {
15- try {
16- return Ok(yield* call(op));
17- } catch (error) {
18- const { input } = yield* ErrContext;
19- yield* input.send(error);
20- return Err(error);
21- }
22- });
23-}
24-
25-export function* safe<T>(opFn: OpFn<T>): Operation<Result<T>> {
26+export function* call<T>(opFn: OpFn<T>): Operation<Result<T>> {
27 try {
28- const value = yield* call(opFn);
29+ const value = yield* unsafeCall(opFn);
30 return Ok(value);
31 } catch (error) {
32 const { input } = yield* ErrContext;
33@@ -53,3 +41,14 @@ export function* safe<T>(opFn: OpFn<T>): Operation<Result<T>> {
34 return Err(error);
35 }
36 }
37+
38+export function* go<T>(op: OpFn<T>): Operation<Task<Result<T>>> {
39+ return yield* spawn(function* () {
40+ const result = yield* call(op);
41+ if (!result.ok) {
42+ const { input } = yield* ErrContext;
43+ yield* input.send(result.error);
44+ }
45+ return result;
46+ });
47+}
+2,
-2
1@@ -1,7 +1,7 @@
2 import type { Channel, Operation, Result } from "../deps.ts";
3 import type { Computation, OpFn } from "../types.ts";
4 import { createChannel, resource, spawn } from "../deps.ts";
5-import { safe } from "./call.ts";
6+import { call } from "./call.ts";
7
8 interface ParallelRet<T> extends Computation<Result<T>[]> {
9 sequence: Channel<Result<T>, void>;
10@@ -19,7 +19,7 @@ export function parallel<T>(operations: OpFn<T>[]) {
11 for (const op of operations) {
12 tasks.push(
13 yield* spawn(function* () {
14- const result = yield* safe(op);
15+ const result = yield* call(op);
16 yield* immediate.input.send(result);
17 return result;
18 }),
+2,
-2
1@@ -1,12 +1,12 @@
2 import type { OpFn } from "../types.ts";
3
4-import { safe } from "./call.ts";
5+import { call } from "./call.ts";
6 import { parallel } from "./parallel.ts";
7
8 export function supervise<T>(op: OpFn<T>) {
9 return function* () {
10 while (true) {
11- yield* safe(op);
12+ yield* call(op);
13 }
14 };
15 }
+65,
-35
1@@ -3,51 +3,81 @@ import { describe, expect, it } from "../test.ts";
2 import { run } from "../deps.ts";
3 import { call } from "../mod.ts";
4
5-describe("call()", () => {
6- it("should call the generator function", async () => {
7- function* me() {
8- return "valid";
9- }
10+const tests = describe("call()");
11
12- await run(function* () {
13- const result = yield* call(me);
14- expect(result).toBe("valid");
15- });
16- });
17+it(tests, "should call the generator function", async () => {
18+ function* me() {
19+ return "valid";
20+ }
21
22- it("should call a normal function with no params", async () => {
23- function me() {
24- return "valid";
25+ await run(function* () {
26+ const result = yield* call(me);
27+ if (!result.ok) {
28+ expect(true).toBe(false);
29+ return;
30 }
31+ expect(result.value).toBe("valid");
32+ });
33+});
34
35- await run(function* () {
36- const result = yield* call(me);
37- expect(result).toBe("valid");
38- });
39+it(tests, "should return an Err()", async () => {
40+ const err = new Error("bang!")
41+ function* me() {
42+ throw err;
43+ }
44+
45+ await run(function* () {
46+ const result = yield* call(me);
47+ if (!result.ok) {
48+ expect(result.error).toEqual(err)
49+ }
50 });
51+});
52
53- it("should call a normal function with params", async () => {
54- function me(v: string) {
55- return "valid " + v;
56+it(tests, "should call a normal function with no params", async () => {
57+ function me() {
58+ return "valid";
59+ }
60+
61+ await run(function* () {
62+ const result = yield* call(me);
63+ if (!result.ok) {
64+ expect(true).toBe(false);
65+ return;
66 }
67+ expect(result.value).toBe("valid");
68+ });
69+});
70
71- await run(function* () {
72- const result = yield* call(() => me("fn"));
73- expect(result).toBe("valid fn");
74- });
75+it(tests, "should call a normal function with params", async () => {
76+ function me(v: string) {
77+ return "valid " + v;
78+ }
79+
80+ await run(function* () {
81+ const result = yield* call(() => me("fn"));
82+ if (!result.ok) {
83+ expect(true).toBe(false);
84+ return;
85+ }
86+ expect(result.value).toBe("valid fn");
87 });
88+});
89
90- it("should call a promise", async () => {
91- const me = () =>
92- new Promise((resolve) => {
93- setTimeout(() => {
94- resolve("valid");
95- }, 10);
96- });
97-
98- await run(function* () {
99- const result = yield* call(me);
100- expect(result).toBe("valid");
101+it(tests, "should call a promise", async () => {
102+ const me = () =>
103+ new Promise((resolve) => {
104+ setTimeout(() => {
105+ resolve("valid");
106+ }, 10);
107 });
108+
109+ await run(function* () {
110+ const result = yield* call(me);
111+ if (!result.ok) {
112+ expect(true).toBe(false);
113+ return;
114+ }
115+ expect(result.value).toBe("valid");
116 });
117 });