repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

commit
86db183
parent
cd48d9d
author
Eric Bower
date
2023-08-27 18:34:17 +0000 UTC
refactor: `call()` to not be safe (#9)

33 files changed,  +260, -416
M mod.ts
M npm.ts
M compose.test.ts
+7, -9
 1@@ -2,6 +2,7 @@ import { asserts, describe, expect, it } from "./test.ts";
 2 
 3 import { Err, Ok, Result, run, sleep } from "./deps.ts";
 4 import { compose } from "./compose.ts";
 5+import { safe } from "./mod.ts";
 6 
 7 const tests = describe("compose()");
 8 
 9@@ -66,9 +67,9 @@ it(tests, "order of execution", async () => {
10   expect(actual).toEqual(expected);
11 });
12 
13-it(tests, "when error is discovered return in `ctx.result`", async () => {
14+it(tests, "when error is discovered, it should throw", async () => {
15   const err = new Error("boom");
16-  const mdw = compose<{ result: Result<void> }>([
17+  const mdw = compose([
18     function* (_, next) {
19       yield* next();
20       asserts.fail();
21@@ -79,14 +80,11 @@ it(tests, "when error is discovered return in `ctx.result`", async () => {
22     },
23   ]);
24   const actual = await run(function* () {
25-    const ctx = { result: Ok(undefined) };
26-    yield* mdw(ctx);
27-    return ctx;
28+    const ctx = {};
29+    const result = yield* safe(() => mdw(ctx));
30+    return result;
31   });
32 
33-  const expected = {
34-    result: Err(err),
35-  };
36-
37+  const expected = Err(err);
38   expect(actual).toEqual(expected);
39 });
M compose.ts
+3, -14
 1@@ -1,11 +1,9 @@
 2-import { call } from "./fx/mod.ts";
 3 import type { Next } from "./query/mod.ts";
 4-import { Instruction, Operation, Result } from "./deps.ts";
 5+import { Instruction, Operation } from "./deps.ts";
 6 
 7 export interface BaseCtx {
 8   // deno-lint-ignore no-explicit-any
 9   [key: string]: any;
10-  result: Result<void>;
11 }
12 
13 export type BaseMiddleware<Ctx extends BaseCtx = BaseCtx, T = unknown> = (
14@@ -43,18 +41,9 @@ export function compose<Ctx extends BaseCtx = BaseCtx, T = unknown>(
15         return;
16       }
17       const nxt = dispatch.bind(null, i + 1);
18-      const result = yield* call(function* () {
19-        if (!fn) return;
20-        return yield* fn(context, nxt);
21-      });
22-      if (!result.ok && context.result.ok) {
23-        context.result = result;
24-      }
25+      yield* fn(context, nxt);
26     }
27 
28-    const result = yield* call(() => dispatch(0));
29-    if (context.result.ok) {
30-      context.result = result;
31-    }
32+    yield* dispatch(0);
33   };
34 }
M deno.lock
+34, -130
  1@@ -12,7 +12,6 @@
  2     "https://deno.land/std@0.140.0/fs/ensure_dir.ts": "9dc109c27df4098b9fc12d949612ae5c9c7169507660dcf9ad90631833209d9d",
  3     "https://deno.land/std@0.140.0/hash/sha256.ts": "803846c7a5a8a5a97f31defeb37d72f519086c880837129934f5d6f72102a8e8",
  4     "https://deno.land/std@0.140.0/io/buffer.ts": "bd0c4bf53db4b4be916ca5963e454bddfd3fcd45039041ea161dbf826817822b",
  5-    "https://deno.land/std@0.140.0/io/types.d.ts": "01f60ae7ec02675b5dbed150d258fc184a78dfe5c209ef53ba4422b46b58822c",
  6     "https://deno.land/std@0.140.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3",
  7     "https://deno.land/std@0.140.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09",
  8     "https://deno.land/std@0.140.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b",
  9@@ -88,7 +87,6 @@
 10     "https://deno.land/x/deno_graph@0.26.0/lib/loader.ts": "380e37e71d0649eb50176a9786795988fc3c47063a520a54b616d7727b0f8629",
 11     "https://deno.land/x/deno_graph@0.26.0/lib/media_type.ts": "222626d524fa2f9ebcc0ec7c7a7d5dfc74cc401cc46790f7c5e0eab0b0787707",
 12     "https://deno.land/x/deno_graph@0.26.0/lib/snippets/deno_graph-de651bc9c240ed8d/src/deno_apis.js": "41192baaa550a5c6a146280fae358cede917ae16ec4e4315be51bef6631ca892",
 13-    "https://deno.land/x/deno_graph@0.26.0/lib/types.d.ts": "2bbdbf895321d1df8db511fab00160a0211c09c2e7cac56c522dd6e9ed6d2ef7",
 14     "https://deno.land/x/deno_graph@0.26.0/mod.ts": "11131ae166580a1c7fa8506ff553751465a81c263d94443f18f353d0c320bc14",
 15     "https://deno.land/x/dnt@0.36.0/lib/compiler.ts": "209ad2e1b294f93f87ec02ade9a0821f942d2e524104552d0aa8ff87021050a5",
 16     "https://deno.land/x/dnt@0.36.0/lib/compiler_transforms.ts": "cbb1fd5948f5ced1aa5c5aed9e45134e2357ce1e7220924c1d7bded30dcd0dd0",
 17@@ -105,47 +103,46 @@
 18     "https://deno.land/x/dnt@0.36.0/lib/utils.ts": "878b7ac7003a10c16e6061aa49dbef9b42bd43174853ebffc9b67ea47eeb11d8",
 19     "https://deno.land/x/dnt@0.36.0/mod.ts": "670f1820f2115e6b6aa4f79999bc796e30cc0d0b45096b84a4e1db9f62b82984",
 20     "https://deno.land/x/dnt@0.36.0/transform.ts": "1b127c5f22699c8ab2545b98aeca38c4e5c21405b0f5342ea17e9c46280ed277",
 21-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/abort-signal.ts": "31224b5f61f1ef58a2acf72bfc1cb9c9bf589f15c263b6555eb06f1b49f77b54",
 22-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/async.ts": "3e007ef245abb240de07029f523c7ef74b9bc383db5716f89d261a5150295777",
 23-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/call.ts": "69c465573031e6315e375c17e01e820239e01a93107866dd9f5ef584b79d13dd",
 24-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/channel.ts": "405659d3453dcc0e3ac4190c38bf9a1140f0a4ef4981985ce3564c7aadba67e9",
 25-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/context.ts": "7d17fcb2fe432eb6da2eeabc425deeac0855d9efd7f2856bdda0a24d62a97968",
 26-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/deps.ts": "91062b4b97089a8cf36550d4f9605d325a0fd19bebc72d15524481a3b56ea669",
 27-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/events.ts": "787b666c5f9fcb8b175a9bcbfdabbfb7b1283da35163fd1f75caf11dd96c2fc0",
 28-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/filter.ts": "ad3ba0ce59923306620da410393c8f248fb9885a55c8cbd1f3670521cd96cc68",
 29-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/first.ts": "6dfacc67b5c6b11bf1df1cf272491ed24a88431ea2eb8a36216b848fbfbe2e8e",
 30-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/future.ts": "7800fde82168c9be4644ec9d2fe532b35a8300baf34a8e1673c6fe6067365bfc",
 31-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/instructions.ts": "c2f99e6a85d9c67896d2980293fb3183aa101bb86eea057322077dd6db0906d6",
 32-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/lazy.ts": "92ea526c5ad7d88290f2a87168e038d482f97421379508d85cf2e049ee60639b",
 33-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/log.ts": "312b6fb4226be5554b945bc9eb7b05ed7b2dd53dd139ca86971bef256eb78997",
 34-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/main.ts": "da8ad0b03e6b49a6fd05da8ad1ce5a2d477a9ee75e2ff3f0a37f19b264797289",
 35-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/map.ts": "26184b51211c87e37396f336c7a8212ea46d9fdea210df208127a6394eee69f9",
 36-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/mod.ts": "5fe0f3ac29c64e13f3692c78b0c1a7b2565d67051c7ca87d8f9d6a652a218841",
 37-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/op.ts": "483465a66fb9fa7529eb8cafbaf94c085b1a5e72876e5d34e44cd4f875b2141b",
 38-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/pipe.ts": "4a28fa93a1ba53661bafb84265f3fcb5614920bbecc0db1c261e1093da3b2cdf",
 39-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/result.ts": "41414d8f376f73c95483982fe81fe9c256a6d836f9b2e4ae31d1a6fc09dec69d",
 40-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/run.ts": "5c1eb89e19246ee4d47ec55c1b7b88842366151c1caabd5f3144b3d59e9d30db",
 41-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/run/block.ts": "41b5e6ba7b80de347589b886e2a414a720b041853e625c6a35ff5d74bb5476f7",
 42-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/run/create.ts": "be9139af2fbe15908256d2d159dec8dca079f94cf02d488074c94fa26fc651fa",
 43-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/run/event-stream.ts": "8c6d40bf315652535a85aa02a61256678dc4e537a4fb436fbe5fecdad794c076",
 44-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/run/frame.ts": "5f3cdd85833e32d94d24da76a2ca584af0a9d60abbe43300beb7cda71250cfda",
 45-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/run/scope.ts": "5c406a4230bd4f4613fdccfa58c69c61b500222a83d92829596b3cc67990427d",
 46-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/sleep.ts": "d7000c05ace8143efd80f1e35243f5521316bc334e4051afe692e1a0c7268304",
 47-    "https://deno.land/x/effection@3.0.0-alpha.9/lib/types.ts": "3eab26c41d8d49cf7a60c433805601e889e814e8c7e0cd1db26a8df48611146f",
 48-    "https://deno.land/x/effection@3.0.0-alpha.9/mod.ts": "ffae461c16d4a1bf24c2179582ab8d5c81ad0df61e4ae2fba51ef5e5bdf90345",
 49+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/abort-signal.ts": "31224b5f61f1ef58a2acf72bfc1cb9c9bf589f15c263b6555eb06f1b49f77b54",
 50+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/all.ts": "acadab8258228e290192f587c8c532428f9093337a9b7688ae55cbc2cacd5caf",
 51+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/async.ts": "3e007ef245abb240de07029f523c7ef74b9bc383db5716f89d261a5150295777",
 52+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/call.ts": "69c465573031e6315e375c17e01e820239e01a93107866dd9f5ef584b79d13dd",
 53+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/channel.ts": "405659d3453dcc0e3ac4190c38bf9a1140f0a4ef4981985ce3564c7aadba67e9",
 54+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/context.ts": "108989ac839d6756e30f6c0afc458bfa3975dd0f970d5173b6b8f8473ce4c335",
 55+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/deps.ts": "91062b4b97089a8cf36550d4f9605d325a0fd19bebc72d15524481a3b56ea669",
 56+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/each.ts": "756f82d8b4ec43623776416b6de6558e7584bbfd437a6a35d44e088667842d32",
 57+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/events.ts": "787b666c5f9fcb8b175a9bcbfdabbfb7b1283da35163fd1f75caf11dd96c2fc0",
 58+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/filter.ts": "ad3ba0ce59923306620da410393c8f248fb9885a55c8cbd1f3670521cd96cc68",
 59+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/first.ts": "6dfacc67b5c6b11bf1df1cf272491ed24a88431ea2eb8a36216b848fbfbe2e8e",
 60+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/future.ts": "7800fde82168c9be4644ec9d2fe532b35a8300baf34a8e1673c6fe6067365bfc",
 61+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/instructions.ts": "d1c1c71b0d28770bf50591750895d6c0f9e8a85eba893543c6c895b5a8cb48f7",
 62+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/lazy.ts": "92ea526c5ad7d88290f2a87168e038d482f97421379508d85cf2e049ee60639b",
 63+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/log.ts": "312b6fb4226be5554b945bc9eb7b05ed7b2dd53dd139ca86971bef256eb78997",
 64+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/main.ts": "03c815f68c561ca2564cf0ebf073d9080a42cc8d2fd087c1c2efc71add0f9aac",
 65+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/map.ts": "26184b51211c87e37396f336c7a8212ea46d9fdea210df208127a6394eee69f9",
 66+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/mod.ts": "05585daea3f16b2fc720b0ed9e5e758c8b60fc802ec32fcad70096f29a71d0e9",
 67+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/op.ts": "483465a66fb9fa7529eb8cafbaf94c085b1a5e72876e5d34e44cd4f875b2141b",
 68+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/pipe.ts": "4a28fa93a1ba53661bafb84265f3fcb5614920bbecc0db1c261e1093da3b2cdf",
 69+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/result.ts": "41414d8f376f73c95483982fe81fe9c256a6d836f9b2e4ae31d1a6fc09dec69d",
 70+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/run.ts": "25523b60a9b5cd64be2f4502062c1d04d8281e2c9cb088ae178e31f2e47ff37e",
 71+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/run/block.ts": "3647f52a4a5b9f7747b78918e70bb8e255030b994285d685850d91e7dcc8c71c",
 72+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/run/create.ts": "be9139af2fbe15908256d2d159dec8dca079f94cf02d488074c94fa26fc651fa",
 73+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/run/event-stream.ts": "8c6d40bf315652535a85aa02a61256678dc4e537a4fb436fbe5fecdad794c076",
 74+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/run/frame.ts": "508ec136d72dbc704c5bc7ccedf579094e5d3057cea7c1ed04b36608599d52b0",
 75+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/run/scope.ts": "358f89062c1d49f8bd8b49c9145c46ad84a8e521711b07ee47bec1cac9836d7c",
 76+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/sleep.ts": "d7000c05ace8143efd80f1e35243f5521316bc334e4051afe692e1a0c7268304",
 77+    "https://deno.land/x/effection@3.0.0-alpha.13/lib/types.ts": "87787b9280ad041eaf7cbbfc1986260764590c01af6f79535b61b5ce4262052e",
 78+    "https://deno.land/x/effection@3.0.0-alpha.13/mod.ts": "ffae461c16d4a1bf24c2179582ab8d5c81ad0df61e4ae2fba51ef5e5bdf90345",
 79     "https://deno.land/x/expect@v0.3.0/expect.ts": "5e6717eddc9df376f7b2c9be6403e016130bb2edbb1acd261a2d6ea9608ee196",
 80     "https://deno.land/x/expect@v0.3.0/matchers.ts": "a37ef4577739247af77a852cdcd69484f999a41ad86ec16bb63a88a7a47a2372",
 81     "https://deno.land/x/expect@v0.3.0/mock.ts": "562d4b1d735d15b0b8e935f342679096b64fe452f86e96714fe8616c0c884914",
 82     "https://deno.land/x/expect@v0.3.0/mod.ts": "0304d2430e1e96ba669a8495e24ba606dcc3d152e1f81aaa8da898cea24e36c2",
 83     "https://deno.land/x/mock_fetch@0.3.0/mod.ts": "7e7806c65ab17b2b684c334c4e565812bdaf504a3e9c938d2bb52bb67428bc89",
 84     "https://deno.land/x/ts_morph@18.0.0/bootstrap/mod.ts": "b53aad517f106c4079971fcd4a81ab79fadc40b50061a3ab2b741a09119d51e9",
 85-    "https://deno.land/x/ts_morph@18.0.0/bootstrap/ts_morph_bootstrap.d.ts": "607e651c5ae5aa57c2ac4090759a6379e809c0cdc42114742ac67353b1a75038",
 86     "https://deno.land/x/ts_morph@18.0.0/bootstrap/ts_morph_bootstrap.js": "6645ac03c5e6687dfa8c78109dc5df0250b811ecb3aea2d97c504c35e8401c06",
 87     "https://deno.land/x/ts_morph@18.0.0/common/DenoRuntime.ts": "6a7180f0c6e90dcf23ccffc86aa8271c20b1c4f34c570588d08a45880b7e172d",
 88     "https://deno.land/x/ts_morph@18.0.0/common/mod.ts": "01985d2ee7da8d1caee318a9d07664774fbee4e31602bc2bb6bb62c3489555ed",
 89-    "https://deno.land/x/ts_morph@18.0.0/common/ts_morph_common.d.ts": "42a92b8263878ef48b60042dbb55adda3face9abdb8d503be4b4f0fe242f25f4",
 90     "https://deno.land/x/ts_morph@18.0.0/common/ts_morph_common.js": "845671ca951073400ce142f8acefa2d39ea9a51e29ca80928642f3f8cf2b7700",
 91-    "https://deno.land/x/ts_morph@18.0.0/common/typescript.d.ts": "21c0786dddf52537611499340166278507eb9784628d321c2cb6acc696cba0f6",
 92     "https://deno.land/x/ts_morph@18.0.0/common/typescript.js": "d5c598b6a2db2202d0428fca5fd79fc9a301a71880831a805d778797d2413c59",
 93     "https://esm.sh/@reduxjs/toolkit@1.9.5?pin=v122": "90302cd219f485943878c9f023338f069f3141b8118438fa70eb5759bac6e4b4",
 94     "https://esm.sh/immer@10.0.2?pin=v122": "7ac87b9c76176de8384a67f8cd93d44f75be1a7496c92707252acb669595c393",
 95@@ -155,128 +152,35 @@
 96     "https://esm.sh/reselect@4.1.8?pin=v122": "486407fec8db8f0c87ba540ff6457dbec3c8ec8fa93a4845383bc8cdb33c6008",
 97     "https://esm.sh/robodux@15.0.1?pin=v122": "51ac2aa6f6fbaac2795f3d34117ba7e77c37e9e3e48bf667a994f6851399bf76",
 98     "https://esm.sh/stable/react@18.2.0/denonext/react.mjs": "3c4f23bcfc53b256fcfaf6f834fa9f584c3bb7be667b2682c6cb6ba8ef88f8e6",
 99-    "https://esm.sh/v118/@types/prop-types@15.7.5/index.d.ts": "6a386ff939f180ae8ef064699d8b7b6e62bc2731a62d7fbf5e02589383838dea",
100-    "https://esm.sh/v118/@types/react@18.2.6/global.d.ts": "549df62b64a71004aee17685b445a8289013daf96246ce4d9b087d13d7a27a61",
101-    "https://esm.sh/v118/@types/react@18.2.6/index.d.ts": "2ef11908f0e5f1cae0a42694e5e38852c976ca99a5d7eecfb71ed6a1187736c7",
102-    "https://esm.sh/v118/@types/scheduler@0.16.3/tracing.d.ts": "f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",
103-    "https://esm.sh/v118/csstype@3.1.2/index.d.ts": "4c68749a564a6facdf675416d75789ee5a557afda8960e0803cf6711fa569288",
104     "https://esm.sh/v122/@babel/runtime@7.22.5/denonext/helpers/esm/extends.js": "3955a0ef35db01cd4efff831a9027924f90fa7d55621cd2b6b8519283e573c21",
105     "https://esm.sh/v122/@babel/runtime@7.22.5/denonext/helpers/esm/objectSpread2.js": "39b25571151291cf2778cd3bb118c5336f7682f878f59fbcf79e2684ae55b194",
106     "https://esm.sh/v122/@babel/runtime@7.22.5/denonext/helpers/esm/objectWithoutPropertiesLoose.js": "fae2539db9a813ad1aab88d10a58d81d9403d242fb3f405e9070fc01c2d8808b",
107     "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/denonext/toolkit.mjs": "5d53890796741e2b082ff3fabe10486c1dfeab2a114cf326718e71ecfcdb9cce",
108-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/autoBatchEnhancer.d.ts": "163311515f4f9c1affba0f76627c04cac57c5c6ab4631cddd3e8fe63e15f6c38",
109-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/configureStore.d.ts": "b4621f57bea1e090c2bf884b79ba024c1f08ec7f55aaafa73ce6437294d170a7",
110-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/createAction.d.ts": "40cd61ce7d19c36d58c2b2723d0ce98a117da61446109c5606f5855ba70af2e3",
111-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/createAsyncThunk.d.ts": "96373f0e963f9660e847f33e339ea6fe5d925cf968786bcaf06530a1a5fe5e52",
112-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/createDraftSafeSelector.d.ts": "76ce4e1118a699d33257c4744e9104ce60259e2aa7c587ee6492e8b6c70eed9d",
113-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/createReducer.d.ts": "640131a2d58a76a0527855c6d2e7a39b9efbb26315c58d6b13885d5e6c584b2e",
114-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/createSlice.d.ts": "e4eeaed797c053bcb4d701cbf6ed0ca494d68df41a56cda1440f035743b83df6",
115-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/devtoolsExtension.d.ts": "c698439b3014a87eeed236e3b0d73af3c65d64daa1c9ee776d179f29fc914b21",
116-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/entities/create_adapter.d.ts": "86047e291068bd62b05fd24479a1b8dc3b25f0e5a7b045c8e7836b937b410a10",
117-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/entities/models.d.ts": "573a8601ded5b0d4cb13710deaba6f587730963b5eef0616fa2833eaf95a2c12",
118-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/getDefaultMiddleware.d.ts": "cd206f3e3df4e2664effd6f20b736497794d93977f2b29a6928a30bc3cb259ae",
119-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/immutableStateInvariantMiddleware.d.ts": "09b07b1bd91a39b16f971bbfe3cec6b85c39fb114127a9ac5264b44673c54e34",
120-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/index.d.ts": "2dd91a9c89118d471af0fae8ab84086b2c3005287176f6d257e728bd3b34513b",
121-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/isPlainObject.d.ts": "9eb137d865a0d950d6ca3464986491ff4630bebfcad9bb8a51693e141414d5b5",
122-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/listenerMiddleware/exceptions.d.ts": "b240581208fa099b57df45ec7b2aed98de1fdec5835122c69c701818dbdb9d99",
123-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/listenerMiddleware/index.d.ts": "1e9413df5d26e38d9b2570595a1d839d49aa7d3daebee8221b3bcb43158a9bf2",
124-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/listenerMiddleware/types.d.ts": "bd18316ccf53436aa56ac095ecb9100ed23a2afe11fdbc77461a1dda9eede8c1",
125-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/mapBuilders.d.ts": "2ce69dce79f37d194e6dc0e610ec62ca2a1a5906e9186748a9fce46299923c9e",
126-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/matchers.d.ts": "4ef992436eae16230a9188019008a43b3264768c126a007e5476f4cb337967f9",
127-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/nanoid.d.ts": "cba4372698930577bb0f3e9f8a959bb9fc9c0d0de9b118d4225584132fea3134",
128-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/serializableStateInvariantMiddleware.d.ts": "f9ff1b947da0074054d30826aaa38e876d1b7027b92324a346ef27c8e0865267",
129-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/tsHelpers.d.ts": "1d7bf5f58c4a24f4a654a2af61207662b910fa429fafa1d32518c4c6cc925c99",
130-    "https://esm.sh/v122/@reduxjs/toolkit@1.9.5/dist/utils.d.ts": "9f14472b238598bdf200a0de9f05dd6568e1171fd753fbd72c01a46bf336145d",
131-    "https://esm.sh/v122/@types/hoist-non-react-statics@3.3.1/index.d.ts": "a84059e8ce2394008282b5a395b28820e4c2fd2da0cd4a15d0d50631b9993854",
132-    "https://esm.sh/v122/@types/react-dom@18.2.4/index.d.ts": "7f1ca21337a49885088a365081b652451342e45d8c29dfbf97243c66a3f60196",
133-    "https://esm.sh/v122/@types/use-sync-external-store@0.0.3/index.d.ts": "61f41da9aaa809e5142b1d849d4e70f3e09913a5cb32c629bf6e61ef27967ff7",
134-    "https://esm.sh/v122/@types/use-sync-external-store@0.0.3/with-selector.d.ts": "da0195f35a277ff34bb5577062514ce75b7a1b12f476d6be3d4489e26fcf00d8",
135     "https://esm.sh/v122/hoist-non-react-statics@3.3.2/denonext/hoist-non-react-statics.mjs": "41018d0142e45a133637f9a3e4da6b8babc22cab2b3ec05cfb202a727da5a0cb",
136     "https://esm.sh/v122/immer@10.0.2/denonext/immer.mjs": "694ebf85b769db4d026ec4b9655a8caaa6ce51776d857df7cedf3fa4774d5297",
137-    "https://esm.sh/v122/immer@10.0.2/dist/immer.d.ts": "058561900fef84704cbc45a29355da6487be9380b8ed0072f3a03693769a5dd0",
138     "https://esm.sh/v122/immer@9.0.21/denonext/immer.mjs": "3819c7f2cc0f19de974517bd2421b80f800a9bc8bcdb87e3b3aaf022640bd7d6",
139-    "https://esm.sh/v122/immer@9.0.21/dist/core/current.d.ts": "99cf6d12499eac02b32c6fa20a8d361a43575ff2fbb774091921c1fa948d046a",
140-    "https://esm.sh/v122/immer@9.0.21/dist/core/finalize.d.ts": "4e39c4f3c1a84861990fdf88c2ae5fd629e2445f6a8f24bff38fcfd95992b3b6",
141-    "https://esm.sh/v122/immer@9.0.21/dist/core/immerClass.d.ts": "16648246bb3e97f7cb5fcc27ed75b158745e05fe838249195d65b37df3c9f4af",
142-    "https://esm.sh/v122/immer@9.0.21/dist/core/proxy.d.ts": "152b6b88eb7d551ddee1aac42693b234c06b7a0914de2c36e947db2080ef8b97",
143-    "https://esm.sh/v122/immer@9.0.21/dist/core/scope.d.ts": "54bbcd36a79afff3b496e8dcba7793bd90756466c41823804f404cec25d6401e",
144-    "https://esm.sh/v122/immer@9.0.21/dist/immer.d.ts": "bc17494a8b7026424ff0c544ea0e3f0502d8f1597daba3c51b7eadee545b321c",
145-    "https://esm.sh/v122/immer@9.0.21/dist/internal.d.ts": "db4029f5b7d82fe41bedb97f6486bc2c64b844e0d0356858679d1aab41c03688",
146-    "https://esm.sh/v122/immer@9.0.21/dist/plugins/all.d.ts": "53361b025e519ff36cbaf171d3d119cb02964a9bf8e5e3a460010067e4048b14",
147-    "https://esm.sh/v122/immer@9.0.21/dist/plugins/es5.d.ts": "20f03fd18464739bf7a688a622c684018c532ed7fdff414da90969d3a4f752f9",
148-    "https://esm.sh/v122/immer@9.0.21/dist/plugins/mapset.d.ts": "72b014db5edcf7c04a88c8eefe7c02664c0513db13aab5810956063ce6716128",
149-    "https://esm.sh/v122/immer@9.0.21/dist/plugins/patches.d.ts": "b7801c3343f3673b0caa4801952d0620b91914d447252aacba88fc1dfb5c7f6a",
150-    "https://esm.sh/v122/immer@9.0.21/dist/types/types-external.d.ts": "9cfa1a46692b51ce18dafbce5259f9c0971832ab1f5201a89a70e23b0b7cf9e2",
151-    "https://esm.sh/v122/immer@9.0.21/dist/types/types-internal.d.ts": "fca1f054dc1076d04d0d98db29996c954e8d02033c9c403ac757e9c10bbe52f3",
152-    "https://esm.sh/v122/immer@9.0.21/dist/utils/common.d.ts": "c4438b8655cc0415fee50e035ce9e238c1c017f2098931cbf2ec425f38a6fce5",
153-    "https://esm.sh/v122/immer@9.0.21/dist/utils/env.d.ts": "f5a35aab17a4fb73b9bca92b3db33cc10649f2af281862a01231ce8d0d500d40",
154-    "https://esm.sh/v122/immer@9.0.21/dist/utils/errors.d.ts": "7a43554d2b957482977f76623246b78fab4bdfee55daae1531300f37602d4a88",
155-    "https://esm.sh/v122/immer@9.0.21/dist/utils/plugins.d.ts": "282ca31db57b351ef685ea90d97dea434755390329b1297f3d67ee06dae144d0",
156     "https://esm.sh/v122/react-dom@18.2.0/denonext/react-dom.mjs": "6efaa0beeb36e4c6567824ef5b24ed7856b64e30ec245fbaedf8bed748e6e121",
157     "https://esm.sh/v122/react-is@16.13.1/denonext/react-is.mjs": "4fc2bb5cfecb53c0f28cd7b730101ff83c05ca06fdd373bc2d6a9bdf662f96d4",
158     "https://esm.sh/v122/react-is@18.2.0/denonext/react-is.mjs": "07ca6a7473ccbb06466e805c8253ade80bd664a0f486cf020864c22c27a60479",
159     "https://esm.sh/v122/react-redux@8.0.5/denonext/react-redux.mjs": "eeba4c3485907ed356f889ce071f63fde42e8397f14dede20d9732e5be188294",
160-    "https://esm.sh/v122/react-redux@8.0.5/es/components/Context.d.ts": "7c66a0e01cd2d48baf1572a2f697565765140cc5cdff8e5a04b06a4295591845",
161-    "https://esm.sh/v122/react-redux@8.0.5/es/components/Provider.d.ts": "311529a26ec91ca60f064079e4133b54e2be281c707326fd86f1f6787969d403",
162-    "https://esm.sh/v122/react-redux@8.0.5/es/components/connect.d.ts": "299ff0a06a3833c39a5766c07d6635eddab9b3ed3c297dd84c122a57480e0f2f",
163-    "https://esm.sh/v122/react-redux@8.0.5/es/connect/selectorFactory.d.ts": "cba4b94121af5365d4ce689e6d711c913748634ef12bf657fd3d28f20d10c0bd",
164-    "https://esm.sh/v122/react-redux@8.0.5/es/exports.d.ts": "bf60c690ff0e05557fa8c1a7439870274741fe8a049ad532339e02f2e0b5d63b",
165-    "https://esm.sh/v122/react-redux@8.0.5/es/hooks/useDispatch.d.ts": "9c6d98ae248560494f7a8e0b1ef2b7cd1eef8a1f5231a8c62d4324d902ff5dd3",
166-    "https://esm.sh/v122/react-redux@8.0.5/es/hooks/useSelector.d.ts": "665c9bbb2ac098a5236f7582fb62e26d1ab9e0a9c8213850494cf3611cc2a0a4",
167-    "https://esm.sh/v122/react-redux@8.0.5/es/hooks/useStore.d.ts": "1d31c2e06d653151138715cc8201527ca7ea2a20e8776ee1c07049233884de72",
168-    "https://esm.sh/v122/react-redux@8.0.5/es/index.d.ts": "a4c3e41066fc4cd9c74c2f98f9e8ee0acbbe6d8f5e59ae403c7f75b0c8fe428e",
169-    "https://esm.sh/v122/react-redux@8.0.5/es/types.d.ts": "bcb9e4bebdccb122cadfab1a87adf15760694d306f9fd9ec24f5238b7f72ccf6",
170-    "https://esm.sh/v122/react-redux@8.0.5/es/utils/Subscription.d.ts": "05be35caefacdcbbc14ff6ec605c9a1458c92491448034c174a401ecb463b4f3",
171-    "https://esm.sh/v122/react-redux@8.0.5/es/utils/reactBatchedUpdates.d.ts": "3a61d355ee0e26e20e6dc05898cfc5b1f57f10996e532b22240bb3d2c5e9730f",
172-    "https://esm.sh/v122/react-redux@8.0.5/es/utils/shallowEqual.d.ts": "42d3863cb9aa6d1ffc8bfe897a1f2203a603e826848c8c41b0c8a786a2f7ecef",
173-    "https://esm.sh/v122/react-redux@8.0.5/es/utils/useSyncExternalStore.d.ts": "6d3d2341958a5fc3beab09a73d9d9280a16ce5412e0dc4b5b7a237af430c5f30",
174     "https://esm.sh/v122/redux-batched-actions@0.5.0/denonext/redux-batched-actions.mjs": "d115abd3bef58a81bb57be5ec013377fa841e9f6cea152f2851560a8e23a032f",
175-    "https://esm.sh/v122/redux-batched-actions@0.5.0/lib/index.d.ts": "38139476cb2f3e6be4947e6e97c293f61c6858b5604f59b1a9908a39421e8bef",
176     "https://esm.sh/v122/redux-thunk@2.4.2/denonext/redux-thunk.mjs": "3de5f6f01b4315e3cc2924ecca9c93150c40b9b9785c2b5882dc60f6b8800b96",
177-    "https://esm.sh/v122/redux-thunk@2.4.2/es/index.d.ts": "c2319b7067346ca83427b59d3e2f63501f71d92bf7559a4ba91be5e00ec12324",
178-    "https://esm.sh/v122/redux-thunk@2.4.2/es/types.d.ts": "ea3b2c86e942ca9808195d90bda3aae12dfb8fddd43b67668e238aa6753ce3a8",
179     "https://esm.sh/v122/redux@4.2.1/denonext/redux.mjs": "8269d22284abebf2be1bbbbbcc53d1842b7858102f1f81e7df1d0144b688f5a4",
180-    "https://esm.sh/v122/redux@4.2.1/index.d.ts": "fd624f7d7b264922476685870f08c5e1c6d6a0f05dee2429a9747b41f6b699d4",
181     "https://esm.sh/v122/reselect@4.1.8/denonext/reselect.mjs": "f8199f9e44453876a9ea6b5d1caedc0fe1ae789a73217543b1e6193e1edc0db7",
182-    "https://esm.sh/v122/reselect@4.1.8/es/defaultMemoize.d.ts": "2d8a1d85b6155ca124eb6ce4d1043471e77b7b8aedda8f2eedb631aac1057416",
183-    "https://esm.sh/v122/reselect@4.1.8/es/index.d.ts": "55a54814090dda59f242a9c891a6a57a985350e5dc0156646a42e88f400c8dd4",
184-    "https://esm.sh/v122/reselect@4.1.8/es/types.d.ts": "0cf2ff23a287d45bf80b88e0c3aefa60881546a0184cae70af91fbc308d016dd",
185-    "https://esm.sh/v122/reselect@4.1.8/es/versionedTypes/index.d.ts": "ed1c984ea8ee3824ab9e262580b845d407f8ca998d7e324a468981e2b461bad3",
186-    "https://esm.sh/v122/reselect@4.1.8/es/versionedTypes/ts47-mergeParameters.d.ts": "1b3a9c3b73e5b61b48c6fc131806b5197a8243e2fa863956717173fbef934420",
187     "https://esm.sh/v122/robodux@15.0.1/denonext/robodux.mjs": "31ba627f958ded9bdcaa7db1bd9bd57f610bb0cbefd871e1286e578f9a7c719a",
188-    "https://esm.sh/v122/robodux@15.0.1/dist/combine.d.ts": "f450e144d24536a0793cf1775aae2356705245c5e724047d4bedc2f8001ad788",
189-    "https://esm.sh/v122/robodux@15.0.1/dist/create-action.d.ts": "61f663dd8b8fd207a4a2e274e86601f92400c2979b9691b71a982f353c19d2f0",
190-    "https://esm.sh/v122/robodux@15.0.1/dist/create-assign.d.ts": "bf1f5a48d6b40310799d392178973eba60ae39273e85a8e9ffcbff8cded20200",
191-    "https://esm.sh/v122/robodux@15.0.1/dist/create-list-table.d.ts": "300926e447d1ddb582a1a086483719a9f07ee3af50c51727bf534d029936f1ca",
192-    "https://esm.sh/v122/robodux@15.0.1/dist/create-list.d.ts": "131c84be65e76bff5be662ef3d7e08d4a665e2bd1a3b7c3f6dcc82004b4ccd51",
193-    "https://esm.sh/v122/robodux@15.0.1/dist/create-loader-table.d.ts": "0f6f08d4db08212f2dd3dadb2cd84190fac29d376428e0df7e9155ecdeed4efb",
194-    "https://esm.sh/v122/robodux@15.0.1/dist/create-loader.d.ts": "f2325a8588a434f725dd621c3d0d16d6c7f023c5158cd87dca8f70c4f2bd98bb",
195-    "https://esm.sh/v122/robodux@15.0.1/dist/create-map.d.ts": "2851c7ad3861c25035b8bd4e61d894af7164cb04b921e8258432ef601be9eeb8",
196-    "https://esm.sh/v122/robodux@15.0.1/dist/create-reducer.d.ts": "a0f32cafe42727eef6c67eb211dc77f19ad5a2d53d6dceaf1c87d0468df5cd13",
197-    "https://esm.sh/v122/robodux@15.0.1/dist/create-slice.d.ts": "56a3d4d6469100edfb88ba672ee2035bba2e1f807b2cbca9b88b1047952b16d6",
198-    "https://esm.sh/v122/robodux@15.0.1/dist/create-table.d.ts": "b72f2a6924ff17af20ff9198366261322c3d8793741188ee387bad675306b253",
199-    "https://esm.sh/v122/robodux@15.0.1/dist/index.d.ts": "b87f84ed5171496f497914f3cc7d65121f59bd0e8982b6d392f63f19006b0645",
200-    "https://esm.sh/v122/robodux@15.0.1/dist/types.d.ts": "f3a61fa962ed1917c97804a3127b2e6ccea283bdbe7b990dc4d3c2f0434eeca6",
201     "https://esm.sh/v122/scheduler@0.23.0/denonext/scheduler.mjs": "69005eb830c0a486d51875e52d1a85443dc8d32b0b6ad1e3f06baceb55ed4cba",
202     "https://esm.sh/v122/use-sync-external-store@1.2.0/denonext/cjs/use-sync-external-store-shim.production.min.js": "5be7011cae1c9c79ad30989c95370a6d97083e01bb98ba76a333347e03af85db",
203     "https://esm.sh/v122/use-sync-external-store@1.2.0/denonext/cjs/use-sync-external-store-shim/with-selector.production.min.js": "5fdb24919bfa6f0c749ce7dab27e1f3a9c4d246ec4727de5ebfbbd7640c1ee58",
204     "https://esm.sh/v122/use-sync-external-store@1.2.0/denonext/shim.js": "1f6aef1d1752cc8267b0252931ddd0bf92df44016ab573b0decaf2c8935cb01b",
205-    "https://esm.sh/v122/use-sync-external-store@1.2.0/denonext/shim/with-selector.js": "4e787e36c6f83276e81b7818e316658e66c392ad69c60db1fbf87073d990f28c",
206-    "https://esm.sh/v128/@types/prop-types@15.7.5/index.d.ts": "6a386ff939f180ae8ef064699d8b7b6e62bc2731a62d7fbf5e02589383838dea",
207-    "https://esm.sh/v128/@types/react@18.2.14/global.d.ts": "549df62b64a71004aee17685b445a8289013daf96246ce4d9b087d13d7a27a61",
208-    "https://esm.sh/v128/@types/react@18.2.14/index.d.ts": "9aac3002309f46089b251d57e7b16c20bb0e8be711867bd308009fb33562b46c",
209-    "https://esm.sh/v128/@types/react@18.2.15/global.d.ts": "549df62b64a71004aee17685b445a8289013daf96246ce4d9b087d13d7a27a61",
210-    "https://esm.sh/v128/@types/react@18.2.15/index.d.ts": "f55ede57bc191e4c9c326fc86393abaa7b20ea3b34199e4c0b118a703a4481b6",
211-    "https://esm.sh/v128/@types/scheduler@0.16.3/tracing.d.ts": "f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",
212-    "https://esm.sh/v128/csstype@3.1.2/index.d.ts": "4c68749a564a6facdf675416d75789ee5a557afda8960e0803cf6711fa569288"
213+    "https://esm.sh/v122/use-sync-external-store@1.2.0/denonext/shim/with-selector.js": "4e787e36c6f83276e81b7818e316658e66c392ad69c60db1fbf87073d990f28c"
214   },
215   "npm": {
216     "specifiers": {
217-      "@types/node": "@types/node@18.11.18"
218+      "@types/node": "@types/node@18.16.19"
219     },
220     "packages": {
221-      "@types/node@18.11.18": {
222-        "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
223+      "@types/node@18.16.19": {
224+        "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
225         "dependencies": {}
226       }
227     }
M deps.ts
+8, -5
 1@@ -1,28 +1,33 @@
 2-import type { Result } from "https://deno.land/x/effection@3.0.0-alpha.9/mod.ts";
 3+import type { Result } from "https://deno.land/x/effection@3.0.0-alpha.13/mod.ts";
 4 export type {
 5   Channel,
 6   Instruction,
 7   Operation,
 8+  Port,
 9   Scope,
10   Stream,
11+  Subscription,
12   Task,
13-} from "https://deno.land/x/effection@3.0.0-alpha.9/mod.ts";
14+} from "https://deno.land/x/effection@3.0.0-alpha.13/mod.ts";
15 export {
16   action,
17   createChannel,
18   createContext,
19   createScope,
20+  each,
21   Err,
22   expect,
23   filter,
24   getframe,
25+  main,
26   Ok,
27   resource,
28   run,
29   sleep,
30   spawn,
31+  suspend,
32   useAbortSignal,
33-} from "https://deno.land/x/effection@3.0.0-alpha.9/mod.ts";
34+} from "https://deno.land/x/effection@3.0.0-alpha.13/mod.ts";
35 
36 export type { Result };
37 
38@@ -54,8 +59,6 @@ export type {
39 export {
40   combineReducers,
41   configureStore,
42-  createImmutableStateInvariantMiddleware,
43-  createSerializableStateInvariantMiddleware,
44   getDefaultMiddleware,
45 } from "https://esm.sh/@reduxjs/toolkit@1.9.5?pin=v122";
46 export {
M fx/call.test.ts
+9, -24
 1@@ -12,11 +12,7 @@ it(tests, "should call the generator function", async () => {
 2 
 3   await run(function* () {
 4     const result = yield* call(me);
 5-    if (!result.ok) {
 6-      expect(true).toBe(false);
 7-      return;
 8-    }
 9-    expect(result.value).toBe("valid");
10+    expect(result).toBe("valid");
11   });
12 });
13 
14@@ -27,9 +23,10 @@ it(tests, "should return an Err()", async () => {
15   }
16 
17   await run(function* () {
18-    const result = yield* call(me);
19-    if (!result.ok) {
20-      expect(result.error).toEqual(err);
21+    try {
22+      yield* call(me);
23+    } catch (err) {
24+      expect(err).toEqual(err);
25     }
26   });
27 });
28@@ -41,11 +38,7 @@ it(tests, "should call a normal function with no params", async () => {
29 
30   await run(function* () {
31     const result = yield* call(me);
32-    if (!result.ok) {
33-      expect(true).toBe(false);
34-      return;
35-    }
36-    expect(result.value).toBe("valid");
37+    expect(result).toEqual("valid");
38   });
39 });
40 
41@@ -56,17 +49,13 @@ it(tests, "should call a normal function with params", async () => {
42 
43   await run(function* () {
44     const result = yield* call(() => me("fn"));
45-    if (!result.ok) {
46-      expect(true).toBe(false);
47-      return;
48-    }
49-    expect(result.value).toBe("valid fn");
50+    expect(result).toEqual("valid fn");
51   });
52 });
53 
54 it(tests, "should call a promise", async () => {
55   const me = () =>
56-    new Promise((resolve) => {
57+    new Promise<string>((resolve) => {
58       setTimeout(() => {
59         resolve("valid");
60       }, 10);
61@@ -74,10 +63,6 @@ it(tests, "should call a promise", async () => {
62 
63   await run(function* () {
64     const result = yield* call(me);
65-    if (!result.ok) {
66-      expect(true).toBe(false);
67-      return;
68-    }
69-    expect(result.value).toBe("valid");
70+    expect(result).toEqual("valid");
71   });
72 });
M fx/call.ts
+3, -3
 1@@ -23,16 +23,16 @@ export function* toOperation<T>(opFn: OpFn<T>): Operation<T> {
 2   return result;
 3 }
 4 
 5-export function unsafeCall<T>(op: OpFn<T>): Operation<T> {
 6+export function call<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* call<T>(opFn: OpFn<T>): Operation<Result<T>> {
14+export function* safe<T>(opFn: OpFn<T>): Operation<Result<T>> {
15   try {
16-    const value = yield* unsafeCall(opFn);
17+    const value = yield* call(opFn);
18     return Ok(value);
19   } catch (error) {
20     return Err(error);
D fx/cancelled.ts
+0, -6
1@@ -1,6 +0,0 @@
2-import { getframe } from "../deps.ts";
3-
4-export function* cancelled() {
5-  const frame = yield* getframe();
6-  return frame.context["cancelled"] || false;
7-}
M fx/mod.ts
+0, -1
1@@ -1,6 +1,5 @@
2 export * from "./parallel.ts";
3 export * from "./call.ts";
4-export * from "./cancelled.ts";
5 export * from "./race.ts";
6 export * from "./request.ts";
7 export * from "./watch.ts";
M fx/parallel.test.ts
+12, -11
 1@@ -1,27 +1,26 @@
 2 import { describe, expect, it } from "../test.ts";
 3 import type { Operation, Result } from "../deps.ts";
 4-import { Err, Ok, run, sleep, spawn } from "../deps.ts";
 5-import { forEach } from "../iter.ts";
 6+import { each, Err, Ok, run, sleep, spawn } from "../deps.ts";
 7 
 8 import { parallel } from "./parallel.ts";
 9 
10 const test = describe("parallel()");
11 
12 interface Defer<T> {
13-  promise: Operation<T>;
14+  promise: Promise<T>;
15   resolve: (t: T) => void;
16   reject: (t: Error) => void;
17 }
18 
19 function defer<T>(): Defer<T> {
20-  let resolve;
21-  let reject;
22+  let resolve: (t: T) => void = () => {};
23+  let reject: (t: Error) => void = () => {};
24   const promise = new Promise<T>((res, rej) => {
25     resolve = res;
26     reject = rej;
27   });
28 
29-  return { resolve, reject, promise } as any;
30+  return { resolve, reject, promise };
31 }
32 
33 it(
34@@ -41,9 +40,10 @@ it(
35       ]);
36 
37       const res: Result<string>[] = [];
38-      yield* forEach(results.immediate.output, function* (val) {
39+      for (const val of yield* each(results.immediate.output)) {
40         res.push(val);
41-      });
42+        yield* each.next;
43+      }
44 
45       yield* results;
46       return res;
47@@ -71,9 +71,10 @@ it(
48 
49       const res: Result<string>[] = [];
50       const { output } = results.sequence;
51-      yield* forEach(output, function* (val) {
52+      for (const val of yield* each(output)) {
53         res.push(val);
54-      });
55+        yield* each.next;
56+      }
57 
58       yield* results;
59       return res;
60@@ -108,7 +109,7 @@ it(
61 
62 it(test, "should return empty array", async () => {
63   let actual;
64-  await run(function* () {
65+  await run(function* (): Operation<void> {
66     const results = yield* parallel([]);
67     actual = yield* results;
68   });
M fx/parallel.ts
+2, -2
 1@@ -2,7 +2,7 @@ import type { Channel, Operation, Result } from "../deps.ts";
 2 import type { Computation, OpFn } from "../types.ts";
 3 import { createChannel, resource, spawn } from "../deps.ts";
 4 
 5-import { call } from "./call.ts";
 6+import { safe } from "./call.ts";
 7 
 8 export interface ParallelRet<T> extends Computation<Result<T>[]> {
 9   sequence: Channel<Result<T>, void>;
10@@ -20,7 +20,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* call(op);
15+            const result = yield* safe(op);
16             yield* immediate.input.send(result);
17             return result;
18           }),
M fx/request.ts
+3, -7
 1@@ -1,4 +1,4 @@
 2-import { Err, expect, Ok, useAbortSignal } from "../deps.ts";
 3+import { expect, useAbortSignal } from "../deps.ts";
 4 
 5 export function* request(url: string | URL | Request, opts?: RequestInit) {
 6   const signal = yield* useAbortSignal();
 7@@ -7,10 +7,6 @@ export function* request(url: string | URL | Request, opts?: RequestInit) {
 8 }
 9 
10 export function* json(response: Response) {
11-  try {
12-    const result = yield* expect(response.json());
13-    return Ok(result);
14-  } catch (error) {
15-    return Err(error);
16-  }
17+  const result = yield* expect(response.json());
18+  return result;
19 }
M fx/watch.ts
+2, -2
 1@@ -1,12 +1,12 @@
 2 import type { OpFn } from "../types.ts";
 3 
 4-import { call } from "./call.ts";
 5+import { safe } 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* call(op);
12+      yield* safe(op);
13     }
14   };
15 }
D iter.ts
+0, -16
 1@@ -1,16 +0,0 @@
 2-import type { Operation, Stream } from "./deps.ts";
 3-
 4-export function* forEach<T>(
 5-  stream: Stream<T, void>,
 6-  each?: (val: T) => Operation<void>,
 7-) {
 8-  const msgList = yield* stream;
 9-  while (true) {
10-    const next = yield* msgList.next();
11-    if (next.done) {
12-      return next.value;
13-    } else if (each) {
14-      yield* each(next.value);
15-    }
16-  }
17-}
M mod.ts
+6, -1
 1@@ -1,7 +1,6 @@
 2 export * from "./fx/mod.ts";
 3 export * from "./query/mod.ts";
 4 export * from "./types.ts";
 5-export * from "./iter.ts";
 6 export * from "./compose.ts";
 7 export * from "./action.ts";
 8 export {
 9@@ -9,19 +8,25 @@ export {
10   createChannel,
11   createContext,
12   createScope,
13+  each,
14   Err,
15   getframe,
16+  main,
17   Ok,
18   resource,
19   run,
20   sleep,
21   spawn,
22+  useAbortSignal,
23 } from "./deps.ts";
24 export type {
25   Channel,
26   Instruction,
27   Operation,
28+  Port,
29   Result,
30   Scope,
31+  Stream,
32+  Subscription,
33   Task,
34 } from "./deps.ts";
M npm.ts
+2, -2
 1@@ -30,9 +30,9 @@ async function main() {
 2       },
 3     ],
 4     mappings: {
 5-      "https://deno.land/x/effection@3.0.0-alpha.9/mod.ts": {
 6+      "https://deno.land/x/effection@3.0.0-alpha.13/mod.ts": {
 7         name: "effection",
 8-        version: "3.0.0-alpha.9",
 9+        version: "3.0.0-alpha.13",
10       },
11       "https://esm.sh/react@18.2.0?pin=v122": {
12         name: "react",
M query/api.test.ts
+29, -27
  1@@ -8,10 +8,11 @@ import {
  2   updateStore,
  3 } from "../store/mod.ts";
  4 import { createQueryState } from "../action.ts";
  5+import { sleep } from "../test.ts";
  6+import { safe } from "../mod.ts";
  7 
  8 import { queryCtx, requestMonitor, urlParser } from "./middleware.ts";
  9 import { createApi } from "./api.ts";
 10-import { sleep } from "../test.ts";
 11 import { createKey } from "./create-key.ts";
 12 import type { ApiCtx } from "./types.ts";
 13 
 14@@ -61,7 +62,7 @@ it(tests, "createApi - POST", async () => {
 15       });
 16       yield* next();
 17 
 18-      const buff = yield* call(() => {
 19+      const buff = yield* safe(() => {
 20         if (!ctx.response) throw new Error("no response");
 21         const res = ctx.response.arrayBuffer();
 22         return res;
 23@@ -83,7 +84,7 @@ it(tests, "createApi - POST", async () => {
 24     },
 25   );
 26 
 27-  const store = await configureStore({ initialState: { users: {} } });
 28+  const store = configureStore({ initialState: { users: {} } });
 29   store.run(query.bootup);
 30 
 31   store.dispatch(createUser({ email: mockUser.email }));
 32@@ -93,7 +94,7 @@ it(tests, "createApi - POST", async () => {
 33   });
 34 });
 35 
 36-it(tests, "POST with uri", async () => {
 37+it(tests, "POST with uri", () => {
 38   const query = createApi();
 39   query.use(queryCtx);
 40   query.use(urlParser);
 41@@ -135,12 +136,12 @@ it(tests, "POST with uri", async () => {
 42     },
 43   );
 44 
 45-  const store = await configureStore({ initialState: { users: {} } });
 46+  const store = configureStore({ initialState: { users: {} } });
 47   store.run(query.bootup);
 48   store.dispatch(createUser({ email: mockUser.email }));
 49 });
 50 
 51-it(tests, "middleware - with request fn", async () => {
 52+it(tests, "middleware - with request fn", () => {
 53   const query = createApi();
 54   query.use(queryCtx);
 55   query.use(urlParser);
 56@@ -155,12 +156,12 @@ it(tests, "middleware - with request fn", async () => {
 57     { supervisor: takeEvery },
 58     query.request({ method: "POST" }),
 59   );
 60-  const store = await configureStore({ initialState: { users: {} } });
 61+  const store = configureStore({ initialState: { users: {} } });
 62   store.run(query.bootup);
 63   store.dispatch(createUser());
 64 });
 65 
 66-it(tests, "run() on endpoint action - should run the effect", async () => {
 67+it(tests, "run() on endpoint action - should run the effect", () => {
 68   const api = createApi<TestCtx>();
 69   api.use(api.routes());
 70   let acc = "";
 71@@ -179,12 +180,12 @@ it(tests, "run() on endpoint action - should run the effect", async () => {
 72     expect(acc).toEqual("ab");
 73   });
 74 
 75-  const store = await configureStore({ initialState: { users: {} } });
 76+  const store = configureStore({ initialState: { users: {} } });
 77   store.run(api.bootup);
 78   store.dispatch(action2());
 79 });
 80 
 81-it(tests, "run() from a normal saga", async () => {
 82+it(tests, "run() from a normal saga", () => {
 83   const api = createApi();
 84   api.use(api.routes());
 85   let acc = "";
 86@@ -196,7 +197,7 @@ it(tests, "run() from a normal saga", async () => {
 87   });
 88   const action2 = () => ({ type: "ACTION" });
 89   function* onAction() {
 90-    const ctx = yield* call(() => action1.run(action1({ id: "1" })));
 91+    const ctx = yield* safe(() => action1.run(action1({ id: "1" })));
 92     if (!ctx.ok) {
 93       throw new Error("no ctx");
 94     }
 95@@ -214,7 +215,7 @@ it(tests, "run() from a normal saga", async () => {
 96     yield* task;
 97   }
 98 
 99-  const store = await configureStore({ initialState: { users: {} } });
100+  const store = configureStore({ initialState: { users: {} } });
101   store.run(() => keepAlive([api.bootup, watchAction]));
102   store.dispatch(action2());
103 });
104@@ -237,7 +238,7 @@ it(tests, "createApi with hash key on a large post", async () => {
105     function* processUsers(ctx, next) {
106       ctx.cache = true;
107       yield* next();
108-      const buff = yield* call(() => {
109+      const buff = yield* safe(() => {
110         if (!ctx.response) {
111           throw new Error("no response");
112         }
113@@ -268,7 +269,7 @@ it(tests, "createApi with hash key on a large post", async () => {
114   const email = mockUser.email + "9";
115   const largetext = "abc-def-ghi-jkl-mno-pqr".repeat(100);
116 
117-  const store = await configureStore({
118+  const store = configureStore({
119     initialState: { ...createQueryState(), users: {} },
120   });
121   store.run(query.bootup);
122@@ -313,7 +314,7 @@ it(tests, "createApi - two identical endpoints", async () => {
123     },
124   );
125 
126-  const store = await configureStore({ initialState: { users: {} } });
127+  const store = configureStore({ initialState: { users: {} } });
128   store.run(api.bootup);
129   store.dispatch(first());
130   store.dispatch(second());
131@@ -328,7 +329,7 @@ interface TestCtx<P = any, S = any, E = any> extends ApiCtx<P, S, E> {
132 }
133 
134 // this is strictly for testing types
135-it(tests, "ensure types for get() endpoint", async () => {
136+it(tests, "ensure types for get() endpoint", () => {
137   const api = createApi<TestCtx>();
138   api.use(api.routes());
139   api.use(function* (ctx, next) {
140@@ -352,7 +353,7 @@ it(tests, "ensure types for get() endpoint", async () => {
141     },
142   );
143 
144-  const store = await configureStore({ initialState: { users: {} } });
145+  const store = configureStore({ initialState: { users: {} } });
146   store.run(api.bootup);
147 
148   store.dispatch(action1({ id: "1" }));
149@@ -365,7 +366,7 @@ interface FetchUserProps {
150 type FetchUserCtx = TestCtx<FetchUserProps>;
151 
152 // this is strictly for testing types
153-it(tests, "ensure ability to cast `ctx` in function definition", async () => {
154+it(tests, "ensure ability to cast `ctx` in function definition", () => {
155   const api = createApi<TestCtx>();
156   api.use(api.routes());
157   api.use(function* (ctx, next) {
158@@ -389,7 +390,7 @@ it(tests, "ensure ability to cast `ctx` in function definition", async () => {
159     },
160   );
161 
162-  const store = await configureStore({ initialState: { users: {} } });
163+  const store = configureStore({ initialState: { users: {} } });
164   store.run(api.bootup);
165   store.dispatch(action1({ id: "1" }));
166   expect(acc).toEqual(["1", "wow"]);
167@@ -401,7 +402,7 @@ type FetchUserSecondCtx = TestCtx<any, { result: string }>;
168 it(
169   tests,
170   "ensure ability to cast `ctx` in function definition with no props",
171-  async () => {
172+  () => {
173     const api = createApi<TestCtx>();
174     api.use(api.routes());
175     api.use(function* (ctx, next) {
176@@ -424,20 +425,21 @@ it(
177       },
178     );
179 
180-    const store = await configureStore({ initialState: { users: {} } });
181+    const store = configureStore({ initialState: { users: {} } });
182     store.run(api.bootup);
183     store.dispatch(action1());
184     expect(acc).toEqual(["wow"]);
185   },
186 );
187 
188-it(tests, "should bubble up error", async () => {
189+it(tests, "should bubble up error", () => {
190   let error: any = null;
191   const api = createApi();
192-  api.use(function* (ctx, next) {
193-    yield* next();
194-    if (!ctx.result.ok) {
195-      error = ctx.result.error;
196+  api.use(function* (_, next) {
197+    try {
198+      yield* next();
199+    } catch (err) {
200+      error = err;
201     }
202   });
203   api.use(queryCtx);
204@@ -453,7 +455,7 @@ it(tests, "should bubble up error", async () => {
205     },
206   );
207 
208-  const store = await configureStore({ initialState: { users: {} } });
209+  const store = configureStore({ initialState: { users: {} } });
210   store.run(api.bootup);
211   store.dispatch(fetchUser());
212   expect(error.message).toBe(
M query/fetch.test.ts
+10, -10
 1@@ -46,7 +46,7 @@ it(
 2       },
 3     );
 4 
 5-    const store = await configureStore<QueryState>({
 6+    const store = configureStore<QueryState>({
 7       initialState: createQueryState(),
 8     });
 9     store.run(api.bootup);
10@@ -95,7 +95,7 @@ it(
11       },
12     );
13 
14-    const store = await configureStore<QueryState>({
15+    const store = configureStore<QueryState>({
16       initialState: createQueryState(),
17     });
18     store.run(api.bootup);
19@@ -137,7 +137,7 @@ it(tests, "fetch - error handling", async () => {
20     },
21   );
22 
23-  const store = await configureStore<QueryState>({
24+  const store = configureStore<QueryState>({
25     initialState: createQueryState(),
26   });
27   store.run(api.bootup);
28@@ -179,7 +179,7 @@ it(tests, "fetch - status 204", async () => {
29     },
30   );
31 
32-  const store = await configureStore<QueryState>({
33+  const store = configureStore<QueryState>({
34     initialState: createQueryState(),
35   });
36   store.run(api.bootup);
37@@ -222,7 +222,7 @@ it(tests, "fetch - malformed json", async () => {
38     },
39   );
40 
41-  const store = await configureStore<QueryState>({
42+  const store = configureStore<QueryState>({
43     initialState: createQueryState(),
44   });
45   store.run(api.bootup);
46@@ -271,7 +271,7 @@ it(tests, "fetch - POST", async () => {
47     },
48   );
49 
50-  const store = await configureStore<QueryState>({
51+  const store = configureStore<QueryState>({
52     initialState: createQueryState(),
53   });
54   store.run(api.bootup);
55@@ -333,7 +333,7 @@ it(tests, "fetch - POST multiple endpoints with same uri", async () => {
56     },
57   );
58 
59-  const store = await configureStore<QueryState>({
60+  const store = configureStore<QueryState>({
61     initialState: createQueryState(),
62   });
63   store.run(api.bootup);
64@@ -371,7 +371,7 @@ it(
65       },
66     );
67 
68-    const store = await configureStore<QueryState>({
69+    const store = configureStore<QueryState>({
70       initialState: createQueryState(),
71     });
72     store.run(api.bootup);
73@@ -418,7 +418,7 @@ it(
74       fetchRetry((n) => (n > 4 ? -1 : 10)),
75     ]);
76 
77-    const store = await configureStore<QueryState>({
78+    const store = configureStore<QueryState>({
79       initialState: createQueryState(),
80     });
81     store.run(api.bootup);
82@@ -460,7 +460,7 @@ it(
83       fetchRetry((n) => (n > 2 ? -1 : 10)),
84     ]);
85 
86-    const store = await configureStore<QueryState>({
87+    const store = configureStore<QueryState>({
88       initialState: createQueryState(),
89     });
90     store.run(api.bootup);
M query/fetch.ts
+8, -8
 1@@ -1,6 +1,6 @@
 2-import { call } from "../fx/mod.ts";
 3 import { sleep } from "../deps.ts";
 4 import { compose } from "../compose.ts";
 5+import { safe } from "../mod.ts";
 6 
 7 import { noop } from "./util.ts";
 8 import type { FetchCtx, FetchJsonCtx, Next } from "./types.ts";
 9@@ -59,7 +59,7 @@ export function* jsonMdw<CurCtx extends FetchJsonCtx = FetchJsonCtx>(
10     return;
11   }
12 
13-  const data = yield* call(() => {
14+  const data = yield* safe(() => {
15     const resp = ctx.response;
16     if (!resp) throw new Error("response is falsy");
17     return resp[ctx.bodyType]();
18@@ -146,11 +146,11 @@ export function* fetchMdw<CurCtx extends FetchCtx = FetchCtx>(
19 ) {
20   const { url, ...req } = ctx.req();
21   const request = new Request(url, req);
22-  const response = yield* call(() => fetch(request));
23-  if (response.ok) {
24-    ctx.response = response.value;
25+  const result = yield* safe(() => fetch(request));
26+  if (result.ok) {
27+    ctx.response = result.value;
28   } else {
29-    throw response.error;
30+    throw result.error;
31   }
32   yield* next();
33 }
34@@ -212,8 +212,8 @@ export function fetchRetry<CurCtx extends FetchJsonCtx = FetchJsonCtx>(
35     let waitFor = backoff(attempt);
36     while (waitFor >= 1) {
37       yield* sleep(waitFor);
38-      yield* call(() => fetchMdw(ctx, noop));
39-      yield* call(() => jsonMdw(ctx, noop));
40+      yield* safe(() => fetchMdw(ctx, noop));
41+      yield* safe(() => jsonMdw(ctx, noop));
42 
43       if (ctx.response.ok) {
44         return;
M query/middleware.test.ts
+21, -21
  1@@ -1,6 +1,5 @@
  2 import { assertLike, asserts, describe, expect, it } from "../test.ts";
  3 import { sleep as delay } from "../deps.ts";
  4-import { call } from "../fx/mod.ts";
  5 import {
  6   createApi,
  7   createKey,
  8@@ -26,6 +25,7 @@ import {
  9   undoer,
 10   updateStore,
 11 } from "../store/mod.ts";
 12+import { safe } from "../mod.ts";
 13 
 14 interface User {
 15   id: string;
 16@@ -47,7 +47,7 @@ const jsonBlob = (data: any) => {
 17 
 18 const tests = describe("middleware");
 19 
 20-it(tests, "basic", async () => {
 21+it(tests, "basic", () => {
 22   const query = createApi<ApiCtx>();
 23   query.use(queryCtx);
 24   query.use(urlParser);
 25@@ -97,7 +97,7 @@ it(tests, "basic", async () => {
 26     },
 27   );
 28 
 29-  const store = await configureStore({
 30+  const store = configureStore({
 31     initialState: {
 32       ...createQueryState(),
 33       users: {},
 34@@ -117,7 +117,7 @@ it(tests, "basic", async () => {
 35   });
 36 });
 37 
 38-it(tests, "with loader", async () => {
 39+it(tests, "with loader", () => {
 40   const api = createApi<ApiCtx>();
 41   api.use(requestMonitor());
 42   api.use(storeMdw());
 43@@ -145,7 +145,7 @@ it(tests, "with loader", async () => {
 44     },
 45   );
 46 
 47-  const store = await configureStore<UserState>({
 48+  const store = configureStore<UserState>({
 49     initialState: { ...createQueryState(), users: {} },
 50   });
 51   store.run(api.bootup);
 52@@ -161,7 +161,7 @@ it(tests, "with loader", async () => {
 53   });
 54 });
 55 
 56-it(tests, "with item loader", async () => {
 57+it(tests, "with item loader", () => {
 58   const api = createApi<ApiCtx>();
 59   api.use(requestMonitor());
 60   api.use(storeMdw());
 61@@ -188,7 +188,7 @@ it(tests, "with item loader", async () => {
 62     },
 63   );
 64 
 65-  const store = await configureStore<UserState>({
 66+  const store = configureStore<UserState>({
 67     initialState: { ...createQueryState(), users: {} },
 68   });
 69   store.run(api.bootup);
 70@@ -208,7 +208,7 @@ it(tests, "with item loader", async () => {
 71   });
 72 });
 73 
 74-it(tests, "with POST", async () => {
 75+it(tests, "with POST", () => {
 76   const query = createApi();
 77   query.use(queryCtx);
 78   query.use(urlParser);
 79@@ -254,7 +254,7 @@ it(tests, "with POST", async () => {
 80     },
 81   );
 82 
 83-  const store = await configureStore<UserState>({
 84+  const store = configureStore<UserState>({
 85     initialState: { ...createQueryState(), users: {} },
 86   });
 87   store.run(query.bootup);
 88@@ -262,7 +262,7 @@ it(tests, "with POST", async () => {
 89   store.dispatch(createUser({ email: mockUser.email }));
 90 });
 91 
 92-it(tests, "simpleCache", async () => {
 93+it(tests, "simpleCache", () => {
 94   const api = createApi<ApiCtx>();
 95   api.use(requestMonitor());
 96   api.use(storeMdw());
 97@@ -275,7 +275,7 @@ it(tests, "simpleCache", async () => {
 98   });
 99 
100   const fetchUsers = api.get("/users", { supervisor: takeEvery }, api.cache());
101-  const store = await configureStore<UserState>({
102+  const store = configureStore<UserState>({
103     initialState: { ...createQueryState(), users: {} },
104   });
105   store.run(api.bootup);
106@@ -294,7 +294,7 @@ it(tests, "simpleCache", async () => {
107   });
108 });
109 
110-it(tests, "overriding default loader behavior", async () => {
111+it(tests, "overriding default loader behavior", () => {
112   const api = createApi<ApiCtx>();
113   api.use(requestMonitor());
114   api.use(storeMdw());
115@@ -326,7 +326,7 @@ it(tests, "overriding default loader behavior", async () => {
116     },
117   );
118 
119-  const store = await configureStore<UserState>({
120+  const store = configureStore<UserState>({
121     initialState: { ...createQueryState(), users: {} },
122   });
123   store.run(api.bootup);
124@@ -344,7 +344,7 @@ it(tests, "overriding default loader behavior", async () => {
125   });
126 });
127 
128-it(tests, "undo", async () => {
129+it(tests, "undo", () => {
130   const api = createApi<UndoCtx>();
131   api.use(requestMonitor());
132   api.use(storeMdw());
133@@ -368,7 +368,7 @@ it(tests, "undo", async () => {
134     },
135   );
136 
137-  const store = await configureStore<UserState>({
138+  const store = configureStore<UserState>({
139     initialState: { ...createQueryState(), users: {} },
140   });
141   store.run(api.bootup);
142@@ -386,7 +386,7 @@ it(tests, "undo", async () => {
143   });
144 });
145 
146-it(tests, "requestMonitor - error handler", async () => {
147+it(tests, "requestMonitor - error handler", () => {
148   let err = false;
149   console.error = (msg: string) => {
150     if (err) return;
151@@ -407,7 +407,7 @@ it(tests, "requestMonitor - error handler", async () => {
152 
153   const fetchUsers = query.create(`/users`, { supervisor: takeEvery });
154 
155-  const store = await configureStore<UserState>({
156+  const store = configureStore<UserState>({
157     initialState: { ...createQueryState(), users: {} },
158   });
159   store.run(query.bootup);
160@@ -438,7 +438,7 @@ it(tests, "createApi with own key", async () => {
161       ctx.cache = true;
162       ctx.key = theTestKey; // or some calculated key //
163       yield* next();
164-      const buff = yield* call(() => {
165+      const buff = yield* safe(() => {
166         if (!ctx.response) throw new Error("no response");
167         return ctx.response.arrayBuffer();
168       });
169@@ -464,7 +464,7 @@ it(tests, "createApi with own key", async () => {
170     },
171   );
172   const newUEmail = mockUser.email + ".org";
173-  const store = await configureStore<UserState>({
174+  const store = configureStore<UserState>({
175     initialState: { ...createQueryState(), users: {} },
176   });
177   store.run(query.bootup);
178@@ -509,7 +509,7 @@ it(tests, "createApi with custom key but no payload", async () => {
179       ctx.cache = true;
180       ctx.key = theTestKey; // or some calculated key //
181       yield* next();
182-      const buff = yield* call(() => {
183+      const buff = yield* safe(() => {
184         if (!ctx.response) throw new Error("no response");
185         return ctx.response?.arrayBuffer();
186       });
187@@ -535,7 +535,7 @@ it(tests, "createApi with custom key but no payload", async () => {
188     },
189   );
190 
191-  const store = await configureStore<UserState>({
192+  const store = configureStore<UserState>({
193     initialState: { ...createQueryState(), users: {} },
194   });
195   store.run(query.bootup);
M query/pipe.test.ts
+32, -29
  1@@ -126,7 +126,7 @@ const tests = describe("createPipe()");
  2 it(
  3   tests,
  4   "when create a query fetch pipeline - execute all middleware and save to redux",
  5-  async () => {
  6+  () => {
  7     const api = createPipe<RoboCtx>();
  8     api.use(api.routes());
  9     api.use(convertNameToUrl);
 10@@ -135,7 +135,7 @@ it(
 11     api.use(processTickets);
 12     const fetchUsers = api.create(`/users`, { supervisor: takeEvery });
 13 
 14-    const store = await configureStore<TestState>({
 15+    const store = configureStore<TestState>({
 16       initialState: { ...createQueryState(), users: {}, tickets: {} },
 17     });
 18     store.run(api.bootup);
 19@@ -153,7 +153,7 @@ it(
 20 it(
 21   tests,
 22   "when providing a generator the to api.create function - should call that generator before all other middleware",
 23-  async () => {
 24+  () => {
 25     const api = createPipe<RoboCtx>();
 26     api.use(api.routes());
 27     api.use(convertNameToUrl);
 28@@ -173,7 +173,7 @@ it(
 29       yield* put(fetchUsers());
 30     });
 31 
 32-    const store = await configureStore<TestState>({
 33+    const store = configureStore<TestState>({
 34       initialState: { ...createQueryState(), users: {}, tickets: {} },
 35     });
 36     store.run(api.bootup);
 37@@ -187,13 +187,14 @@ it(
 38   },
 39 );
 40 
 41-it(tests, "error handling", async () => {
 42-  let called = false;
 43+it(tests, "error handling", () => {
 44+  let called;
 45   const api = createPipe<RoboCtx>();
 46   api.use(api.routes());
 47-  api.use(function* upstream(ctx, next) {
 48-    yield* next();
 49-    if (!ctx.result.ok) {
 50+  api.use(function* upstream(_, next) {
 51+    try {
 52+      yield* next();
 53+    } catch (_) {
 54       called = true;
 55     }
 56   });
 57@@ -203,13 +204,13 @@ it(tests, "error handling", async () => {
 58 
 59   const action = api.create(`/error`, { supervisor: takeEvery });
 60 
 61-  const store = await configureStore({ initialState: {} });
 62+  const store = configureStore({ initialState: {} });
 63   store.run(api.bootup);
 64   store.dispatch(action());
 65   asserts.assertStrictEquals(called, true);
 66 });
 67 
 68-it(tests, "error handling inside create", async () => {
 69+it(tests, "error handling inside create", () => {
 70   let called = false;
 71   const api = createPipe<RoboCtx>();
 72   api.use(api.routes());
 73@@ -220,25 +221,27 @@ it(tests, "error handling inside create", async () => {
 74   const action = api.create(
 75     `/error`,
 76     { supervisor: takeEvery },
 77-    function* (ctx, next) {
 78-      yield* next();
 79-      if (!ctx.result.ok) {
 80+    function* (_, next) {
 81+      try {
 82+        yield* next();
 83+      } catch (_) {
 84         called = true;
 85       }
 86     },
 87   );
 88-  const store = await configureStore({ initialState: {} });
 89+  const store = configureStore({ initialState: {} });
 90   store.run(api.bootup);
 91   store.dispatch(action());
 92   asserts.assertStrictEquals(called, true);
 93 });
 94 
 95-it(tests, "error inside endpoint mdw", async () => {
 96+it(tests, "error inside endpoint mdw", () => {
 97   let called = false;
 98   const query = createPipe();
 99-  query.use(function* (ctx, next) {
100-    yield* next();
101-    if (!ctx.result.ok) {
102+  query.use(function* (_, next) {
103+    try {
104+      yield* next();
105+    } catch (_) {
106       called = true;
107     }
108   });
109@@ -253,7 +256,7 @@ it(tests, "error inside endpoint mdw", async () => {
110     },
111   );
112 
113-  const store = await configureStore({
114+  const store = configureStore({
115     initialState: {
116       ...createQueryState(),
117       users: {},
118@@ -264,7 +267,7 @@ it(tests, "error inside endpoint mdw", async () => {
119   asserts.assertEquals(called, true);
120 });
121 
122-it(tests, "create fn is an array", async () => {
123+it(tests, "create fn is an array", () => {
124   const api = createPipe<RoboCtx>();
125   api.use(api.routes());
126   api.use(function* (ctx, next) {
127@@ -289,12 +292,12 @@ it(tests, "create fn is an array", async () => {
128     },
129   ]);
130 
131-  const store = await configureStore({ initialState: {} });
132+  const store = configureStore({ initialState: {} });
133   store.run(api.bootup);
134   store.dispatch(action());
135 });
136 
137-it(tests, "run() on endpoint action - should run the effect", async () => {
138+it(tests, "run() on endpoint action - should run the effect", () => {
139   const api = createPipe<RoboCtx>();
140   api.use(api.routes());
141   let acc = "";
142@@ -328,7 +331,7 @@ it(tests, "run() on endpoint action - should run the effect", async () => {
143     },
144   );
145 
146-  const store = await configureStore({ initialState: {} });
147+  const store = configureStore({ initialState: {} });
148   store.run(api.bootup);
149   store.dispatch(action2());
150 });
151@@ -364,7 +367,7 @@ it(tests, "middleware order of execution", async () => {
152     },
153   );
154 
155-  const store = await configureStore({ initialState: {} });
156+  const store = configureStore({ initialState: {} });
157   store.run(api.bootup);
158   store.dispatch(action());
159 
160@@ -394,7 +397,7 @@ it(tests, "retry with actionFn", async () => {
161     },
162   );
163 
164-  const store = await configureStore({ initialState: {} });
165+  const store = configureStore({ initialState: {} });
166   store.run(api.bootup);
167   store.dispatch(action());
168 
169@@ -424,7 +427,7 @@ it(tests, "retry with actionFn with payload", async () => {
170     },
171   );
172 
173-  const store = await configureStore({ initialState: {} });
174+  const store = configureStore({ initialState: {} });
175   store.run(api.bootup);
176   store.dispatch(action({ page: 1 }));
177 
178@@ -432,7 +435,7 @@ it(tests, "retry with actionFn with payload", async () => {
179   asserts.assertEquals(acc, "agag");
180 });
181 
182-it(tests, "should only call thunk once", async () => {
183+it(tests, "should only call thunk once", () => {
184   const api = createPipe<RoboCtx>();
185   api.use(api.routes());
186   let acc = "";
187@@ -454,7 +457,7 @@ it(tests, "should only call thunk once", async () => {
188     },
189   );
190 
191-  const store = await configureStore({ initialState: {} });
192+  const store = configureStore({ initialState: {} });
193   store.run(api.bootup);
194   store.dispatch(action2());
195   asserts.assertEquals(acc, "a");
M query/react.test.ts
+1, -1
1@@ -50,7 +50,7 @@ const setupTest = async () => {
2     });
3   });
4 
5-  const store = await configureStore<{ user?: User }>({
6+  const store = configureStore<{ user?: User }>({
7     initialState: {},
8   });
9   store.run(api.bootup);
M react.ts
+1, -1
1@@ -1,2 +1,2 @@
2 export * from "./query/react.ts";
3-export * from "./store/react.ts";
4+export { Provider, useDispatch, useSelector } from "./deps.ts";
M redux/fx.ts
+3, -3
 1@@ -75,7 +75,7 @@ export function* takeEvery<T>(
 2   pattern: ActionPattern,
 3   op: (action: Action) => Operation<T>,
 4 ) {
 5-  return yield* spawn(function* () {
 6+  return yield* spawn(function* (): Operation<void> {
 7     while (true) {
 8       const action = yield* take(pattern);
 9       if (!action) continue;
10@@ -88,7 +88,7 @@ export function* takeLatest<T>(
11   pattern: ActionPattern,
12   op: (action: Action) => Operation<T>,
13 ) {
14-  return yield* spawn(function* () {
15+  return yield* spawn(function* (): Operation<void> {
16     let lastTask;
17     while (true) {
18       const action = yield* take(pattern);
19@@ -105,7 +105,7 @@ export function* takeLeading<T>(
20   pattern: ActionPattern,
21   op: (action: Action) => Operation<T>,
22 ) {
23-  return yield* spawn(function* () {
24+  return yield* spawn(function* (): Operation<void> {
25     while (true) {
26       const action = yield* take(pattern);
27       if (!action) continue;
M redux/middleware.test.ts
+11, -8
 1@@ -1,6 +1,6 @@
 2 import { describe, expect, it } from "../test.ts";
 3 import { call } from "../fx/mod.ts";
 4-import { Action } from "../deps.ts";
 5+import { Action, sleep } from "../deps.ts";
 6 
 7 import { createFxMiddleware, select } from "./mod.ts";
 8 
 9@@ -26,21 +26,24 @@ function createStore<S>(state: S): Store<S> {
10   return store;
11 }
12 
13-it(tests, "should be able to grab values from store", async () => {
14+it.only(tests, "should be able to grab values from store", async () => {
15   const store = createStore({ user: { id: "1" } });
16-  const { run, middleware } = createFxMiddleware();
17+  const { scope, middleware } = createFxMiddleware();
18   middleware(store);
19-  await run(function* () {
20-    const actual = yield* select((s: TestState) => s.user);
21-    expect(actual).toEqual({ id: "1" });
22+
23+  let actual;
24+  await scope.run(function* () {
25+    yield* sleep(100);
26+    actual = yield* select((s: TestState) => s.user);
27   });
28+  expect(actual).toEqual({ id: "1" });
29 });
30 
31 it(tests, "should be able to grab store from a nested call", async () => {
32   const store = createStore({ user: { id: "2" } });
33-  const { run, middleware } = createFxMiddleware();
34+  const { scope, middleware } = createFxMiddleware();
35   middleware(store);
36-  await run(function* () {
37+  await scope.run(function* () {
38     const actual = yield* call(function* () {
39       return yield* select((s: TestState) => s.user);
40     });
M redux/middleware.ts
+10, -13
 1@@ -14,8 +14,7 @@ import {
 2   createScope,
 3   enableBatching,
 4 } from "../deps.ts";
 5-import type { OpFn } from "../types.ts";
 6-import { call, parallel } from "../fx/mod.ts";
 7+import { parallel } from "../fx/mod.ts";
 8 
 9 import { ActionContext, emit, StoreContext, StoreLike } from "./fx.ts";
10 import { reducers as queryReducers } from "./query.ts";
11@@ -43,19 +42,17 @@ function* send(action: AnyAction) {
12   }
13 }
14 
15-export function createFxMiddleware(scope: Scope = createScope()) {
16-  function run<T>(op: OpFn<T>) {
17-    const task = scope.run(function* runner() {
18-      return yield* call(op);
19-    });
20-
21-    return task;
22+export function createFxMiddleware(initScope?: Scope) {
23+  let scope: Scope;
24+  if (initScope) {
25+    scope = initScope;
26+  } else {
27+    const tuple = createScope();
28+    scope = tuple[0];
29   }
30 
31   function middleware<S = unknown, T = unknown>(store: StoreLike<S>) {
32-    scope.run(function* () {
33-      yield* StoreContext.set(store);
34-    });
35+    scope.set(StoreContext, store);
36 
37     return (next: (a: Action) => T) => (action: Action) => {
38       const result = next(action); // hit reducers
39@@ -66,7 +63,7 @@ export function createFxMiddleware(scope: Scope = createScope()) {
40     };
41   }
42 
43-  return { run, scope, middleware };
44+  return { scope, middleware, run: scope.run };
45 }
46 
47 // deno-lint-ignore no-explicit-any
D result.ts
+0, -14
 1@@ -1,14 +0,0 @@
 2-import { Ok, Result } from "./deps.ts";
 3-
 4-export function resultAll<T>(results: Result<T>[]): Result<T[]> {
 5-  const agg: T[] = [];
 6-  for (let i = 0; i < results.length; i += 1) {
 7-    const result = results[i];
 8-    if (result.ok) {
 9-      agg.push(result.value);
10-    } else {
11-      return result;
12-    }
13-  }
14-  return Ok(agg);
15-}
M store/configureStore.test.ts
+8, -6
 1@@ -11,19 +11,21 @@ interface TestState {
 2 }
 3 
 4 it(tests, "should be able to grab values from store", async () => {
 5-  const store = await configureStore({ initialState: { user: { id: "1" } } });
 6+  let actual;
 7+  const store = configureStore({ initialState: { user: { id: "1" } } });
 8   await store.run(function* () {
 9-    const actual = yield* select((s: TestState) => s.user);
10-    expect(actual).toEqual({ id: "1" });
11+    actual = yield* select((s: TestState) => s.user);
12   });
13+  expect(actual).toEqual({ id: "1" });
14 });
15 
16 it(tests, "should be able to grab store from a nested call", async () => {
17-  const store = await configureStore({ initialState: { user: { id: "2" } } });
18+  let actual;
19+  const store = configureStore({ initialState: { user: { id: "2" } } });
20   await store.run(function* () {
21-    const actual = yield* call(function* () {
22+    actual = yield* call(function* () {
23       return yield* select((s: TestState) => s.user);
24     });
25-    expect(actual).toEqual({ id: "2" });
26   });
27+  expect(actual).toEqual({ id: "2" });
28 });
M store/put.test.ts
+4, -4
 1@@ -28,7 +28,7 @@ it(putTests, "should send actions through channel", async () => {
 2     });
 3   }
 4 
 5-  const store = await configureStore({ initialState: {} });
 6+  const store = configureStore({ initialState: {} });
 7   await store.run(() => genFn("arg"));
 8 
 9   const expected = ["arg", "2"];
10@@ -58,7 +58,7 @@ it(putTests, "should handle nested puts", async () => {
11     yield* spawn(genA);
12   }
13 
14-  const store = await configureStore({ initialState: {} });
15+  const store = configureStore({ initialState: {} });
16   await store.run(() => root());
17 
18   const expected = ["put b", "put a"];
19@@ -76,7 +76,7 @@ it(
20       yield* sleep(0);
21     }
22 
23-    const store = await configureStore({ initialState: {} });
24+    const store = configureStore({ initialState: {} });
25     await store.run(() => root());
26     expect(true).toBe(true);
27   },
28@@ -104,7 +104,7 @@ it(
29       yield* tsk;
30     }
31 
32-    const store = await configureStore({ initialState: {} });
33+    const store = configureStore({ initialState: {} });
34     await store.run(() => root());
35     const expected = ["didn't get missed"];
36     expect(actual).toEqual(expected);
D store/react.ts
+0, -1
1@@ -1 +0,0 @@
2-export { Provider, useDispatch, useSelector } from "../deps.ts";
M store/store.test.ts
+8, -13
 1@@ -4,7 +4,7 @@ import { asserts, describe, it } from "../test.ts";
 2 
 3 import { StoreContext, StoreUpdateContext } from "./context.ts";
 4 import { put, take, updateStore } from "./fx.ts";
 5-import { createStore, register } from "./store.ts";
 6+import { configureStore, createStore } from "./store.ts";
 7 
 8 const tests = describe("store");
 9 
10@@ -53,13 +53,12 @@ it(
11   tests,
12   "update store and receives update from channel `StoreUpdateContext`",
13   async () => {
14-    const scope = createScope();
15+    const [scope] = createScope();
16     const initialState: Partial<State> = {
17       users: { 1: { id: "1", name: "testing" }, 2: { id: "2", name: "wow" } },
18       dev: false,
19     };
20-    const store = createStore({ scope, initialState });
21-    await register(store);
22+    createStore({ scope, initialState });
23 
24     await scope.run(function* (): Operation<Result<void>[]> {
25       const result = yield* parallel([
26@@ -87,42 +86,38 @@ it(
27 );
28 
29 it(tests, "update store and receives update from `subscribe()`", async () => {
30-  const scope = createScope();
31   const initialState: Partial<State> = {
32     users: { 1: { id: "1", name: "testing" }, 2: { id: "2", name: "wow" } },
33     dev: false,
34     theme: "",
35     token: "",
36   };
37-  const store = createStore({ scope, initialState });
38-  await register(store);
39+  const store = configureStore({ initialState });
40 
41   store.subscribe(() => {
42     asserts.assertEquals(store.getState(), {
43       users: { 1: { id: "1", name: "eric" }, 3: { id: "", name: "" } },
44+      dev: true,
45       theme: "",
46       token: "",
47-      dev: true,
48     });
49   });
50 
51-  await scope.run(function* () {
52+  await store.run(function* () {
53     yield* updateStore(updateUser({ id: "1", name: "eric" }));
54   });
55 });
56 
57 it(tests, "emit Action and update store", async () => {
58-  const scope = createScope();
59   const initialState: Partial<State> = {
60     users: { 1: { id: "1", name: "testing" }, 2: { id: "2", name: "wow" } },
61     dev: false,
62     theme: "",
63     token: "",
64   };
65-  const store = createStore({ scope, initialState });
66-  await register(store);
67+  const store = configureStore({ initialState });
68 
69-  await scope.run(function* (): Operation<void> {
70+  await store.run(function* (): Operation<void> {
71     const result = yield* parallel([
72       function* (): Operation<void> {
73         const action = yield* take<UpdateUserProps>("UPDATE_USER");
M store/store.ts
+18, -19
 1@@ -9,7 +9,8 @@ import {
 2 } from "../deps.ts";
 3 import { BaseMiddleware, compose } from "../compose.ts";
 4 import type { OpFn } from "../types.ts";
 5-import { call } from "../fx/mod.ts";
 6+import { safe } from "../fx/mod.ts";
 7+import { Next } from "../query/types.ts";
 8 
 9 import type {
10   AnyAction,
11@@ -21,7 +22,6 @@ import type {
12 } from "./types.ts";
13 import { StoreContext, StoreUpdateContext } from "./context.ts";
14 import { put } from "./fx.ts";
15-import { Next } from "../query/types.ts";
16 
17 const stubMsg = "This is merely a stub, not implemented";
18 
19@@ -45,9 +45,17 @@ export interface CreateStore<S extends AnyState> {
20 
21 export function createStore<S extends AnyState>({
22   initialState,
23-  scope = createScope(),
24+  scope: initScope,
25   middleware = [],
26 }: CreateStore<S>): FxStore<S> {
27+  let scope: Scope;
28+  if (initScope) {
29+    scope = initScope;
30+  } else {
31+    const tuple = createScope();
32+    scope = tuple[0];
33+  }
34+
35   let state = initialState;
36   const listeners = new Set<Listener>();
37   enablePatches();
38@@ -133,7 +141,7 @@ export function createStore<S extends AnyState>({
39 
40   function run<T>(op: OpFn<T>): Task<Result<T>> {
41     return scope.run(function* () {
42-      return yield* call(op);
43+      return yield* safe(op);
44     });
45   }
46 
47@@ -157,20 +165,11 @@ export function createStore<S extends AnyState>({
48   };
49 }
50 
51-export function register<S extends AnyState>(store: FxStore<S>) {
52-  const scope = store.getScope();
53-  return scope.run(function* () {
54-    // TODO: fix type
55-    // deno-lint-ignore no-explicit-any
56-    yield* StoreContext.set(store as any);
57-  });
58-}
59-
60-export async function configureStore<S extends AnyState>({
61-  scope = createScope(),
62-  ...props
63-}: CreateStore<S>): Promise<FxStore<S>> {
64-  const store = createStore<S>({ scope, ...props });
65-  await register(store);
66+export function configureStore<S extends AnyState>(
67+  props: CreateStore<S>,
68+): FxStore<S> {
69+  const store = createStore<S>(props);
70+  // deno-lint-ignore no-explicit-any
71+  store.getScope().set(StoreContext, store as any);
72   return store;
73 }
M store/take-helper.test.ts
+3, -3
 1@@ -23,7 +23,7 @@ it(testLatest, "should cancel previous tasks and only use latest", async () => {
 2     yield* take("CANCEL_WATCHER");
 3     yield* task.halt();
 4   }
 5-  const store = await configureStore({ initialState: {} });
 6+  const store = configureStore({ initialState: {} });
 7   const task = store.run(root);
 8 
 9   store.dispatch({ type: "ACTION", payload: "1" });
10@@ -50,7 +50,7 @@ it(testLeading, "should keep first action and discard the rest", async () => {
11     yield* sleep(150);
12     yield* task.halt();
13   }
14-  const store = await configureStore({ initialState: {} });
15+  const store = configureStore({ initialState: {} });
16   const task = store.run(root);
17 
18   store.dispatch({ type: "ACTION", payload: "1" });
19@@ -81,7 +81,7 @@ it(testEvery, "should receive all actions", async () => {
20     actual.push([arg1, arg2, action.payload]);
21   }
22 
23-  const store = await configureStore({ initialState: {} });
24+  const store = configureStore({ initialState: {} });
25   const task = store.run(root);
26 
27   for (let i = 1; i <= loop / 2; i += 1) {
M store/take.test.ts
+2, -2
 1@@ -26,7 +26,7 @@ it(
 2       actual.push(yield* take("action-1"));
 3     }
 4 
 5-    const store = await configureStore({ initialState: {} });
 6+    const store = configureStore({ initialState: {} });
 7     await store.run(root);
 8 
 9     expect(actual).toEqual([
10@@ -86,7 +86,7 @@ it(takeTests, "take from default channel", async () => {
11     }
12   }
13 
14-  const store = await configureStore({ initialState: {} });
15+  const store = configureStore({ initialState: {} });
16   await store.run(genFn);
17 
18   const expected = [