repos / starfx

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

commit
38f52cb
parent
44ddfc9
author
Eric Bower
date
2023-12-01 16:43:33 +0000 UTC
feat: `createBatchMdw` for batching store listener events (#22)

7 files changed,  +82, -89
M deno.lock
+6, -73
  1@@ -1,11 +1,9 @@
  2 {
  3   "version": "3",
  4   "redirects": {
  5-    "https://crux.land/router@0.0.5": "https://crux.land/api/get/2KNRVU.ts",
  6     "https://esm.sh/v128/@types/react@~18.2/index.d.ts": "https://esm.sh/v128/@types/react@18.2.38/index.d.ts"
  7   },
  8   "remote": {
  9-    "https://crux.land/api/get/2KNRVU.ts": "6a77d55844aba78d01520c5ff0b2f0af7f24cc1716a0de8b3bb6bd918c47b5ba",
 10     "https://deno.land/std@0.140.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
 11     "https://deno.land/std@0.140.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49",
 12     "https://deno.land/std@0.140.0/bytes/bytes_list.ts": "67eb118e0b7891d2f389dad4add35856f4ad5faab46318ff99653456c23b025d",
 13@@ -29,8 +27,6 @@
 14     "https://deno.land/std@0.158.0/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c",
 15     "https://deno.land/std@0.158.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832",
 16     "https://deno.land/std@0.158.0/testing/asserts.ts": "8696c488bc98d8d175e74dc652a0ffbc7fca93858da01edc57ed33c1148345da",
 17-    "https://deno.land/std@0.163.0/testing/_test_suite.ts": "2d07073d5460a4e3ec50c55ae822cd9bd136926d7363091379947fef9c73c3e4",
 18-    "https://deno.land/std@0.163.0/testing/bdd.ts": "35060cefd9cc21b414f4d89453b3551a3d52ec50aeff25db432503c5485b2f72",
 19     "https://deno.land/std@0.181.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462",
 20     "https://deno.land/std@0.181.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3",
 21     "https://deno.land/std@0.181.0/fs/_util.ts": "65381f341af1ff7f40198cee15c20f59951ac26e51ddc651c5293e24f9ce6f32",
 22@@ -62,17 +58,6 @@
 23     "https://deno.land/std@0.182.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d",
 24     "https://deno.land/std@0.182.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1",
 25     "https://deno.land/std@0.182.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba",
 26-    "https://deno.land/std@0.185.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e",
 27-    "https://deno.land/std@0.185.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea",
 28-    "https://deno.land/std@0.185.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7",
 29-    "https://deno.land/std@0.185.0/testing/asserts.ts": "e16d98b4d73ffc4ed498d717307a12500ae4f2cbe668f1a215632d19fcffc22f",
 30-    "https://deno.land/std@0.187.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e",
 31-    "https://deno.land/std@0.187.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea",
 32-    "https://deno.land/std@0.187.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7",
 33-    "https://deno.land/std@0.187.0/testing/asserts.ts": "e16d98b4d73ffc4ed498d717307a12500ae4f2cbe668f1a215632d19fcffc22f",
 34-    "https://deno.land/std@0.97.0/fmt/colors.ts": "db22b314a2ae9430ae7460ce005e0a7130e23ae1c999157e3bb77cf55800f7e4",
 35-    "https://deno.land/std@0.97.0/testing/_diff.ts": "961eaf6d9f5b0a8556c9d835bbc6fa74f5addd7d3b02728ba7936ff93364f7a3",
 36-    "https://deno.land/std@0.97.0/testing/asserts.ts": "341292d12eebc44be4c3c2ca101ba8b6b5859cef2fa69d50c217f9d0bfbcfd1f",
 37     "https://deno.land/x/code_block_writer@12.0.0/mod.ts": "2c3448060e47c9d08604c8f40dee34343f553f33edcdfebbf648442be33205e5",
 38     "https://deno.land/x/code_block_writer@12.0.0/utils/string_utils.ts": "60cb4ec8bd335bf241ef785ccec51e809d576ff8e8d29da43d2273b69ce2a6ff",
 39     "https://deno.land/x/continuation@0.1.5/mod.ts": "690def2735046367b3e1b4bc6e51b5912f2ed09c41c7df7a55c060f23720ad33",
 40@@ -88,11 +73,6 @@
 41     "https://deno.land/x/deno_cache@0.5.2/lib/snippets/deno_cache_dir-77bed54ace8005e0/fs.js": "cbe3a976ed63c72c7cb34ef845c27013033a3b11f9d8d3e2c4aa5dda2c0c7af6",
 42     "https://deno.land/x/deno_cache@0.5.2/mod.ts": "0b4d071ad095128bdc2b1bc6e5d2095222dcbae08287261690ee9757e6300db6",
 43     "https://deno.land/x/deno_cache@0.5.2/util.ts": "f3f5a0cfc60051f09162942fb0ee87a0e27b11a12aec4c22076e3006be4cc1e2",
 44-    "https://deno.land/x/deno_graph@0.26.0/lib/deno_graph.generated.js": "2f7ca85b2ceb80ec4b3d1b7f3a504956083258610c7b9a1246238c5b7c68f62d",
 45-    "https://deno.land/x/deno_graph@0.26.0/lib/loader.ts": "380e37e71d0649eb50176a9786795988fc3c47063a520a54b616d7727b0f8629",
 46-    "https://deno.land/x/deno_graph@0.26.0/lib/media_type.ts": "222626d524fa2f9ebcc0ec7c7a7d5dfc74cc401cc46790f7c5e0eab0b0787707",
 47-    "https://deno.land/x/deno_graph@0.26.0/lib/snippets/deno_graph-de651bc9c240ed8d/src/deno_apis.js": "41192baaa550a5c6a146280fae358cede917ae16ec4e4315be51bef6631ca892",
 48-    "https://deno.land/x/deno_graph@0.26.0/mod.ts": "11131ae166580a1c7fa8506ff553751465a81c263d94443f18f353d0c320bc14",
 49     "https://deno.land/x/dir@1.5.1/data_local_dir/mod.ts": "91eb1c4bfadfbeda30171007bac6d85aadacd43224a5ed721bbe56bc64e9eb66",
 50     "https://deno.land/x/dnt@0.38.1/lib/compiler.ts": "209ad2e1b294f93f87ec02ade9a0821f942d2e524104552d0aa8ff87021050a5",
 51     "https://deno.land/x/dnt@0.38.1/lib/compiler_transforms.ts": "f21aba052f5dcf0b0595c734450842855c7f572e96165d3d34f8fed2fc1f7ba1",
 52@@ -109,41 +89,6 @@
 53     "https://deno.land/x/dnt@0.38.1/lib/utils.ts": "878b7ac7003a10c16e6061aa49dbef9b42bd43174853ebffc9b67ea47eeb11d8",
 54     "https://deno.land/x/dnt@0.38.1/mod.ts": "b13349fe77847cf58e26b40bcd58797a8cec5d71b31a1ca567071329c8489de1",
 55     "https://deno.land/x/dnt@0.38.1/transform.ts": "f68743a14cf9bf53bfc9c81073871d69d447a7f9e3453e0447ca2fb78926bb1d",
 56-    "https://deno.land/x/effection@3.0.0-beta.2/lib/abort-signal.ts": "8be1b331b2bc417d70fe4c07e0b806e89972b8eab519ce58beed7ec632ae9048",
 57-    "https://deno.land/x/effection@3.0.0-beta.2/lib/all.ts": "acadab8258228e290192f587c8c532428f9093337a9b7688ae55cbc2cacd5caf",
 58-    "https://deno.land/x/effection@3.0.0-beta.2/lib/async.ts": "086b27b253be944c47c633d105f1657e243cd8c0d35b9a0dc5383528d7235dde",
 59-    "https://deno.land/x/effection@3.0.0-beta.2/lib/call.ts": "1ab6649c2944b72ffd27a495712562311abf414c548ada9cc1c8edea96c46d37",
 60-    "https://deno.land/x/effection@3.0.0-beta.2/lib/channel.ts": "f86b36666463f8f86fc1ac1726a94f0f08dc05559ba710b8eb93581b2b8588e6",
 61-    "https://deno.land/x/effection@3.0.0-beta.2/lib/context.ts": "108989ac839d6756e30f6c0afc458bfa3975dd0f970d5173b6b8f8473ce4c335",
 62-    "https://deno.land/x/effection@3.0.0-beta.2/lib/deps.ts": "91062b4b97089a8cf36550d4f9605d325a0fd19bebc72d15524481a3b56ea669",
 63-    "https://deno.land/x/effection@3.0.0-beta.2/lib/each.ts": "9689346d1db3fedcd87d48c70be5515ad3e18fa4b894755fa53910fb8ad356f3",
 64-    "https://deno.land/x/effection@3.0.0-beta.2/lib/ensure.ts": "c3640cc12c1bc747a8a4086af476840db026d04ea22f45a697d53617b2b1cc66",
 65-    "https://deno.land/x/effection@3.0.0-beta.2/lib/events.ts": "d962e7403d62948642f5a3161f611f4375932aa8702050575f0d538aab7c3467",
 66-    "https://deno.land/x/effection@3.0.0-beta.2/lib/filter.ts": "39f349ee921ba718cf3259e05003255eeeafbb5ca6e437d2d269b1805da2236e",
 67-    "https://deno.land/x/effection@3.0.0-beta.2/lib/first.ts": "5bc321069d2e2b87b6623f626a929d5d5ba32bca32ee03b37bdc1a64722eebb9",
 68-    "https://deno.land/x/effection@3.0.0-beta.2/lib/instructions.ts": "5fd8638e385068adc6c1a896bba02b736d7c2c26e5124d3d063fdbcaf140abec",
 69-    "https://deno.land/x/effection@3.0.0-beta.2/lib/lazy.ts": "92ea526c5ad7d88290f2a87168e038d482f97421379508d85cf2e049ee60639b",
 70-    "https://deno.land/x/effection@3.0.0-beta.2/lib/lift.ts": "0c622bf0359f92235547b57efa66139b265a7b259428e6883469de0b3af32f5d",
 71-    "https://deno.land/x/effection@3.0.0-beta.2/lib/main.ts": "a0deaf1d1d958ef7a5821d8ac3dfbd190a47608d603798a5fc3b0c2309a724da",
 72-    "https://deno.land/x/effection@3.0.0-beta.2/lib/map.ts": "1a0c369dad53affc4b798a04142de637a75f981385acafcafd26bdc569675bc2",
 73-    "https://deno.land/x/effection@3.0.0-beta.2/lib/mod.ts": "f7189b02d008baba1166d33779379b12f7104e0b6d373194270ac126a73ba82d",
 74-    "https://deno.land/x/effection@3.0.0-beta.2/lib/pause.ts": "a690b0d67cf970c34f528df8c61d69eb43deda9817362776f6359f506dc0da45",
 75-    "https://deno.land/x/effection@3.0.0-beta.2/lib/pipe.ts": "4a28fa93a1ba53661bafb84265f3fcb5614920bbecc0db1c261e1093da3b2cdf",
 76-    "https://deno.land/x/effection@3.0.0-beta.2/lib/queue.ts": "80c6234cb6eaba9fd1abdae077e73f51897b099ea54f852b9a744e8eba51302f",
 77-    "https://deno.land/x/effection@3.0.0-beta.2/lib/race.ts": "0c43f24ce5006768f5cbac8d6f5dc07848bafa625cc0bc6c24fb6a2f2a8808f2",
 78-    "https://deno.land/x/effection@3.0.0-beta.2/lib/result.ts": "44e4bdadad155beb9bbfe41948819bbcb9e27a772283e52e89981bd6636a8687",
 79-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run.ts": "b85043bc8b30c0eb0d04654cdd07004b21145f2e3f59f52e39df76558e324ca4",
 80-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run/create.ts": "be9139af2fbe15908256d2d159dec8dca079f94cf02d488074c94fa26fc651fa",
 81-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run/frame.ts": "b9b85112e3168c0fc91e01b1df60f2e911ee1a44314678944d9cbfa71b0641de",
 82-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run/scope.ts": "0e164df8b9825ac1aef3ff1e35a85cf6c82ac48318ba9942d76bf477337895ca",
 83-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run/task.ts": "b4b019d6e32d4c22c83ea9d1cfd64a3d587587080d459aec00aa9e6ba9d49b2a",
 84-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run/types.ts": "c6e413c941613e364604643a084eb432a7ba3ec468e5b0f5341c09b2f54510ef",
 85-    "https://deno.land/x/effection@3.0.0-beta.2/lib/run/value.ts": "d57428b45dfeecc9df1e68dadf8697dbc33cd412e6ffcab9d0ba4368e8c1fbd6",
 86-    "https://deno.land/x/effection@3.0.0-beta.2/lib/shift-sync.ts": "74ecefa9cb2e145a3c52f363319f8d6296b804600852044b7d14bd53bc10b512",
 87-    "https://deno.land/x/effection@3.0.0-beta.2/lib/signal.ts": "da723b43b6bd61ea86dab991e9a6c6249a61d3b1c3c98ef473b160c9383e7d07",
 88-    "https://deno.land/x/effection@3.0.0-beta.2/lib/sleep.ts": "44e3a80248dad7a47066a99a7daec9b318e87d5d211adf27776145544d455689",
 89-    "https://deno.land/x/effection@3.0.0-beta.2/lib/types.ts": "4595c09ccfaae87c5a1d12006c23e5f4083fcd5658c322350f27801a9a9cb348",
 90-    "https://deno.land/x/effection@3.0.0-beta.2/mod.ts": "ffae461c16d4a1bf24c2179582ab8d5c81ad0df61e4ae2fba51ef5e5bdf90345",
 91     "https://deno.land/x/effection@3.0.0-beta.3/lib/abort-signal.ts": "8be1b331b2bc417d70fe4c07e0b806e89972b8eab519ce58beed7ec632ae9048",
 92     "https://deno.land/x/effection@3.0.0-beta.3/lib/all.ts": "acadab8258228e290192f587c8c532428f9093337a9b7688ae55cbc2cacd5caf",
 93     "https://deno.land/x/effection@3.0.0-beta.3/lib/async.ts": "086b27b253be944c47c633d105f1657e243cd8c0d35b9a0dc5383528d7235dde",
 94@@ -179,11 +124,6 @@
 95     "https://deno.land/x/effection@3.0.0-beta.3/lib/sleep.ts": "44e3a80248dad7a47066a99a7daec9b318e87d5d211adf27776145544d455689",
 96     "https://deno.land/x/effection@3.0.0-beta.3/lib/types.ts": "9738143fe6bfd5709a6ff10b6dd065582cfaca1167bf57902cb7bcca89b53dc4",
 97     "https://deno.land/x/effection@3.0.0-beta.3/mod.ts": "ffae461c16d4a1bf24c2179582ab8d5c81ad0df61e4ae2fba51ef5e5bdf90345",
 98-    "https://deno.land/x/expect@v0.3.0/expect.ts": "5e6717eddc9df376f7b2c9be6403e016130bb2edbb1acd261a2d6ea9608ee196",
 99-    "https://deno.land/x/expect@v0.3.0/matchers.ts": "a37ef4577739247af77a852cdcd69484f999a41ad86ec16bb63a88a7a47a2372",
100-    "https://deno.land/x/expect@v0.3.0/mock.ts": "562d4b1d735d15b0b8e935f342679096b64fe452f86e96714fe8616c0c884914",
101-    "https://deno.land/x/expect@v0.3.0/mod.ts": "0304d2430e1e96ba669a8495e24ba606dcc3d152e1f81aaa8da898cea24e36c2",
102-    "https://deno.land/x/mock_fetch@0.3.0/mod.ts": "7e7806c65ab17b2b684c334c4e565812bdaf504a3e9c938d2bb52bb67428bc89",
103     "https://deno.land/x/ts_morph@18.0.0/bootstrap/mod.ts": "b53aad517f106c4079971fcd4a81ab79fadc40b50061a3ab2b741a09119d51e9",
104     "https://deno.land/x/ts_morph@18.0.0/bootstrap/ts_morph_bootstrap.js": "6645ac03c5e6687dfa8c78109dc5df0250b811ecb3aea2d97c504c35e8401c06",
105     "https://deno.land/x/ts_morph@18.0.0/common/DenoRuntime.ts": "6a7180f0c6e90dcf23ccffc86aa8271c20b1c4f34c570588d08a45880b7e172d",
106@@ -192,24 +132,17 @@
107     "https://deno.land/x/ts_morph@18.0.0/common/typescript.js": "d5c598b6a2db2202d0428fca5fd79fc9a301a71880831a805d778797d2413c59",
108     "https://deno.land/x/wasmbuild@0.15.0/cache.ts": "89eea5f3ce6035a1164b3e655c95f21300498920575ade23161421f5b01967f4",
109     "https://deno.land/x/wasmbuild@0.15.0/loader.ts": "d98d195a715f823151cbc8baa3f32127337628379a02d9eb2a3c5902dbccfc02",
110-    "https://esm.sh/immer@10.0.2?pin=v122": "f5441852ba9150f72eb995fc27d5d62c74634ff9db3443690ba9813bb41bf3a6",
111-    "https://esm.sh/react-redux@8.0.5?pin=v122": "3932bbe7b7af1e47962844c5cb3a258d3084bcc5d16235915b16ddd12d99ac1c",
112-    "https://esm.sh/react@18.2.0?pin=v122": "04ad7dc6d11fa27b24c136686a334ecdd19e972fae627cd98cbdc13cdac238c2",
113-    "https://esm.sh/redux-batched-actions@0.5.0?pin=v122": "b04d108cb890d2b128eee6874bd87ca61c07d4e76b89cfd4259e538c6d71f0ff",
114-    "https://esm.sh/redux@4.2.1?pin=v122": "cb93b33d683299991e95af6663dd5c452ddf3c3b98d77a32827c8a7e8b29e86b",
115-    "https://esm.sh/reselect@4.1.8?pin=v122": "8deb34bf285957ed9897171abab8c3e9c332ffc7fb02b2eba7114bf96afe1596",
116+    "https://esm.sh/immer@10.0.2?pin=v122": "7ac87b9c76176de8384a67f8cd93d44f75be1a7496c92707252acb669595c393",
117+    "https://esm.sh/react-redux@8.0.5?pin=v122": "fa98e94dc8803fb84bee9eb08a13f11833f634d381003247207682823887dc51",
118+    "https://esm.sh/react@18.2.0?pin=v122": "8950a34a030620fce8349d6bd3913b3bdb186c5ec7968fa5ba4d054e22d78e6c",
119+    "https://esm.sh/redux-batched-actions@0.5.0?pin=v122": "bb9ba7abde4cbba4352e5d25cf8407795f962e6f7c47b59657ee91834fd6744c",
120+    "https://esm.sh/redux@4.2.1?pin=v122": "94f9684721d9f8f48f86778e03f237c00d771283a8533a1e63000e7539f3a303",
121+    "https://esm.sh/reselect@4.1.8?pin=v122": "486407fec8db8f0c87ba540ff6457dbec3c8ec8fa93a4845383bc8cdb33c6008",
122     "https://esm.sh/robodux@15.0.2?pin=v122": "0311191f385c627ec97a15dc147cbad4367e09169eb1b591a6992b5d707f1446",
123     "https://esm.sh/stable/react@18.2.0/denonext/react.mjs": "3c4f23bcfc53b256fcfaf6f834fa9f584c3bb7be667b2682c6cb6ba8ef88f8e6",
124     "https://esm.sh/v122/@babel/runtime@7.22.5/denonext/helpers/esm/extends.js": "3955a0ef35db01cd4efff831a9027924f90fa7d55621cd2b6b8519283e573c21",
125     "https://esm.sh/v122/@babel/runtime@7.22.5/denonext/helpers/esm/objectSpread2.js": "39b25571151291cf2778cd3bb118c5336f7682f878f59fbcf79e2684ae55b194",
126     "https://esm.sh/v122/@babel/runtime@7.22.5/denonext/helpers/esm/objectWithoutPropertiesLoose.js": "fae2539db9a813ad1aab88d10a58d81d9403d242fb3f405e9070fc01c2d8808b",
127-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/defineProperty.js": "13f1ca9874644d87caf4f1c7c6029600aef3b2282e5be76fc72965d0ec10d8a8",
128-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/extends.js": "a255beed3049780b7227a4ab04033d3fcdc0f5b16e2f40d50868db351d6a4713",
129-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/objectSpread2.js": "4efd3940e87a8f83f150e6a2f8a794888b39b93f89c30a070ad071785be0ada3",
130-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/objectWithoutPropertiesLoose.js": "4c002759b2e90c80ec29dcf7e7c2e3fd2c11efee184891ec3589649f4cb88c5f",
131-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/toPrimitive.js": "3cd6dc027623adf0a661e719d4ac66d207625e1aadbd74ecc3fde6520e92b83c",
132-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/toPropertyKey.js": "9dbde1a53dc209af48a2b456a7607fc93487e429e3902ee93a02e8bafc59c125",
133-    "https://esm.sh/v122/@babel/runtime@7.23.5/denonext/helpers/esm/typeof.js": "63e81169470f8b02123455bebcb637867e3acf10c687712b535e9bc700199b28",
134     "https://esm.sh/v122/hoist-non-react-statics@3.3.2/denonext/hoist-non-react-statics.mjs": "41018d0142e45a133637f9a3e4da6b8babc22cab2b3ec05cfb202a727da5a0cb",
135     "https://esm.sh/v122/immer@10.0.2/denonext/immer.mjs": "694ebf85b769db4d026ec4b9655a8caaa6ce51776d857df7cedf3fa4774d5297",
136     "https://esm.sh/v122/immer@9.0.21/denonext/immer.mjs": "3819c7f2cc0f19de974517bd2421b80f800a9bc8bcdb87e3b3aaf022640bd7d6",
M deps.ts
+1, -0
1@@ -24,6 +24,7 @@ export {
2   createSignal,
3   each,
4   Err,
5+  first,
6   getframe,
7   Ok,
8   resource,
A store/batch.test.ts
+37, -0
 1@@ -0,0 +1,37 @@
 2+import { createBatchMdw } from "./batch.ts";
 3+import { configureStore } from "./store.ts";
 4+import { describe, expect, it } from "../test.ts";
 5+import { createSchema } from "./schema.ts";
 6+import { slice } from "./slice/mod.ts";
 7+import { parallel } from "../fx/mod.ts";
 8+
 9+const batch = describe("batch mdw");
10+
11+it(batch, "should batch notify subscribers based on mdw", async () => {
12+  const schema = createSchema({
13+    cache: slice.table({ empty: {} }),
14+    loaders: slice.loader(),
15+  });
16+  const store = configureStore({
17+    initialState: schema.initialState,
18+    middleware: [createBatchMdw(queueMicrotask)],
19+  });
20+  let counter = 0;
21+  store.subscribe(() => {
22+    counter += 1;
23+  });
24+  await store.run(function* () {
25+    const group: any = yield* parallel([
26+      schema.update(schema.db.cache.add({ "1": "one" })),
27+      schema.update(schema.db.cache.add({ "2": "two" })),
28+      schema.update(schema.db.cache.add({ "3": "three" })),
29+      schema.update(schema.db.cache.add({ "4": "four" })),
30+      schema.update(schema.db.cache.add({ "5": "five" })),
31+      schema.update(schema.db.cache.add({ "6": "six" })),
32+    ]);
33+    yield* group;
34+    // make sure it will still notify subscribers after batched round
35+    yield* schema.update(schema.db.cache.add({ "7": "seven" }));
36+  });
37+  expect(counter).toBe(2);
38+});
A store/batch.ts
+22, -0
 1@@ -0,0 +1,22 @@
 2+import { action } from "../deps.ts";
 3+import { Next } from "../query/types.ts";
 4+import { UpdaterCtx } from "./types.ts";
 5+import { AnyState } from "../types.ts";
 6+
 7+export function createBatchMdw<S extends AnyState>(
 8+  queue: (send: () => void) => void,
 9+) {
10+  let notifying = false;
11+  return function* batchMdw(_: UpdaterCtx<S>, next: Next) {
12+    if (!notifying) {
13+      notifying = true;
14+      yield* action<void>(function* (resolve) {
15+        queue(() => {
16+          notifying = false;
17+          resolve();
18+        });
19+      });
20+      yield* next();
21+    }
22+  };
23+}
M store/fx.ts
+2, -2
 1@@ -24,7 +24,7 @@ export function* updateStore<S extends AnyState>(
 2   return ctx;
 3 }
 4 
 5-export function* emit({
 6+export function emit({
 7   signal,
 8   action,
 9 }: {
10@@ -56,7 +56,7 @@ export function* select<S, R, P>(
11 
12 export function* put(action: AnyAction | AnyAction[]) {
13   const signal = yield* ActionContext;
14-  return yield* emit({
15+  return emit({
16     signal,
17     action,
18   });
M store/mod.ts
+1, -0
1@@ -8,3 +8,4 @@ export * from "./supervisor.ts";
2 export { createSelector } from "../deps.ts";
3 export * from "./slice/mod.ts";
4 export * from "./schema.ts";
5+export * from "./batch.ts";
M store/store.ts
+13, -14
 1@@ -15,7 +15,7 @@ import { safe } from "../fx/mod.ts";
 2 import { Next } from "../query/types.ts";
 3 import type { FxStore, Listener, StoreUpdater, UpdaterCtx } from "./types.ts";
 4 import { ActionContext, StoreContext, StoreUpdateContext } from "./context.ts";
 5-import { put } from "./fx.ts";
 6+import { emit } from "./fx.ts";
 7 import { log } from "../log.ts";
 8 
 9 const stubMsg = "This is merely a stub, not implemented";
10@@ -35,7 +35,7 @@ function observable() {
11 export interface CreateStore<S extends AnyState> {
12   scope?: Scope;
13   initialState: S;
14-  middleware?: BaseMiddleware[];
15+  middleware?: BaseMiddleware<UpdaterCtx<S>>[];
16 }
17 
18 export function createStore<S extends AnyState>({
19@@ -55,6 +55,9 @@ export function createStore<S extends AnyState>({
20   const listeners = new Set<Listener>();
21   enablePatches();
22 
23+  const signal = createSignal<AnyAction, void>();
24+  scope.set(ActionContext, signal);
25+
26   function getScope() {
27     return scope;
28   }
29@@ -103,8 +106,8 @@ export function createStore<S extends AnyState>({
30 
31   function createUpdater() {
32     const fn = compose<UpdaterCtx<S>>([
33-      ...middleware,
34       updateMdw,
35+      ...middleware,
36       notifyChannelMdw,
37       notifyListenersMdw,
38     ]);
39@@ -119,8 +122,9 @@ export function createStore<S extends AnyState>({
40       patches: [],
41       result: Ok(undefined),
42     };
43+
44     yield* mdw(ctx);
45-    // TODO: dev mode only?
46+
47     if (!ctx.result.ok) {
48       yield* log({
49         type: "store:update",
50@@ -130,25 +134,22 @@ export function createStore<S extends AnyState>({
51         },
52       });
53     }
54+
55     return ctx;
56   }
57 
58-  // deno-lint-ignore no-explicit-any
59-  function dispatch(action: AnyAction | AnyAction[]): Task<any> {
60-    return scope.run(function* () {
61-      yield* put(action);
62-    });
63+  function dispatch(action: AnyAction | AnyAction[]) {
64+    emit({ signal, action });
65   }
66 
67   function run<T>(op: Callable<T>): Task<Result<T>> {
68-    return scope.run(function* () {
69-      return yield* safe(op);
70-    });
71+    return scope.run(() => safe(op));
72   }
73 
74   function getInitialState() {
75     return initialState;
76   }
77+
78   return {
79     getScope,
80     getState,
81@@ -174,9 +175,7 @@ export function configureStore<S extends AnyState>(
82   props: CreateStore<S>,
83 ): FxStore<S> {
84   const store = createStore<S>(props);
85-  const signal = createSignal<AnyAction, void>();
86   // deno-lint-ignore no-explicit-any
87   store.getScope().set(StoreContext, store as any);
88-  store.getScope().set(ActionContext, signal);
89   return store;
90 }