saga-toolkit 2.0.4 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +12 -0
- package/example/.env +1 -0
- package/example/package-lock.json +20 -165
- package/example/src/App.js +12 -1
- package/example/src/sagaToolkit.js +24 -8
- package/example/src/sagas.js +19 -1
- package/example/src/slice.js +1 -0
- package/example/src/store/createStore.js +1 -1
- package/index.js +30 -14
- package/package.json +7 -4
- package/sagaToolkit.js +24 -8
- package/test/createStore.js +24 -0
- package/test/sagaToolkit.test.js +95 -0
- package/example/src/App.test.js +0 -8
package/.babelrc
ADDED
package/example/.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SKIP_PREFLIGHT_CHECK=true
|
|
@@ -17,17 +17,24 @@
|
|
|
17
17
|
"react-scripts": "4.0.3",
|
|
18
18
|
"redux": "^4.1.1",
|
|
19
19
|
"redux-saga": "^1.1.3",
|
|
20
|
-
"redux-toolkit": "^1.1.2",
|
|
21
20
|
"saga-toolkit": "file:..",
|
|
22
21
|
"web-vitals": "^1.0.1"
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
"..": {
|
|
26
|
-
"version": "
|
|
25
|
+
"version": "2.0.4",
|
|
27
26
|
"license": "ISC",
|
|
28
|
-
"
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@babel/cli": "^7.16.8",
|
|
29
|
+
"@babel/core": "^7.16.12",
|
|
30
|
+
"@babel/node": "^7.16.8",
|
|
31
|
+
"@babel/preset-env": "^7.16.11",
|
|
32
|
+
"@reduxjs/toolkit": "^1.7.2",
|
|
33
|
+
"babel-jest": "^27.4.6",
|
|
34
|
+
"jest": "^27.4.7",
|
|
35
|
+
"redux": "^4.1.2",
|
|
29
36
|
"redux-saga": "^1.1.3",
|
|
30
|
-
"redux-
|
|
37
|
+
"redux-saga-test-plan": "^4.0.4"
|
|
31
38
|
}
|
|
32
39
|
},
|
|
33
40
|
"node_modules/@babel/code-frame": {
|
|
@@ -8136,14 +8143,6 @@
|
|
|
8136
8143
|
"readable-stream": "^2.3.6"
|
|
8137
8144
|
}
|
|
8138
8145
|
},
|
|
8139
|
-
"node_modules/flux-standard-action": {
|
|
8140
|
-
"version": "0.6.1",
|
|
8141
|
-
"resolved": "https://registry.npmjs.org/flux-standard-action/-/flux-standard-action-0.6.1.tgz",
|
|
8142
|
-
"integrity": "sha1-bzQhG5SDTqHDzDD056+tPQ+/caI=",
|
|
8143
|
-
"dependencies": {
|
|
8144
|
-
"lodash.isplainobject": "^3.2.0"
|
|
8145
|
-
}
|
|
8146
|
-
},
|
|
8147
8146
|
"node_modules/follow-redirects": {
|
|
8148
8147
|
"version": "1.13.2",
|
|
8149
8148
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
|
|
@@ -9325,14 +9324,6 @@
|
|
|
9325
9324
|
"node": ">= 0.4"
|
|
9326
9325
|
}
|
|
9327
9326
|
},
|
|
9328
|
-
"node_modules/invariant": {
|
|
9329
|
-
"version": "2.2.4",
|
|
9330
|
-
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
|
9331
|
-
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
|
9332
|
-
"dependencies": {
|
|
9333
|
-
"loose-envify": "^1.0.0"
|
|
9334
|
-
}
|
|
9335
|
-
},
|
|
9336
9327
|
"node_modules/ip": {
|
|
9337
9328
|
"version": "1.1.5",
|
|
9338
9329
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
|
@@ -10898,50 +10889,16 @@
|
|
|
10898
10889
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
10899
10890
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
|
10900
10891
|
},
|
|
10901
|
-
"node_modules/lodash._basefor": {
|
|
10902
|
-
"version": "3.0.3",
|
|
10903
|
-
"resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz",
|
|
10904
|
-
"integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI="
|
|
10905
|
-
},
|
|
10906
10892
|
"node_modules/lodash._reinterpolate": {
|
|
10907
10893
|
"version": "3.0.0",
|
|
10908
10894
|
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
|
10909
10895
|
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
|
10910
10896
|
},
|
|
10911
|
-
"node_modules/lodash.isarguments": {
|
|
10912
|
-
"version": "3.1.0",
|
|
10913
|
-
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
|
10914
|
-
"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
|
|
10915
|
-
},
|
|
10916
|
-
"node_modules/lodash.isarray": {
|
|
10917
|
-
"version": "3.0.4",
|
|
10918
|
-
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
|
|
10919
|
-
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
|
|
10920
|
-
},
|
|
10921
10897
|
"node_modules/lodash.isequalwith": {
|
|
10922
10898
|
"version": "4.4.0",
|
|
10923
10899
|
"resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz",
|
|
10924
10900
|
"integrity": "sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA="
|
|
10925
10901
|
},
|
|
10926
|
-
"node_modules/lodash.isplainobject": {
|
|
10927
|
-
"version": "3.2.0",
|
|
10928
|
-
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz",
|
|
10929
|
-
"integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=",
|
|
10930
|
-
"dependencies": {
|
|
10931
|
-
"lodash._basefor": "^3.0.0",
|
|
10932
|
-
"lodash.isarguments": "^3.0.0",
|
|
10933
|
-
"lodash.keysin": "^3.0.0"
|
|
10934
|
-
}
|
|
10935
|
-
},
|
|
10936
|
-
"node_modules/lodash.keysin": {
|
|
10937
|
-
"version": "3.0.8",
|
|
10938
|
-
"resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz",
|
|
10939
|
-
"integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=",
|
|
10940
|
-
"dependencies": {
|
|
10941
|
-
"lodash.isarguments": "^3.0.0",
|
|
10942
|
-
"lodash.isarray": "^3.0.0"
|
|
10943
|
-
}
|
|
10944
|
-
},
|
|
10945
10902
|
"node_modules/lodash.memoize": {
|
|
10946
10903
|
"version": "4.1.2",
|
|
10947
10904
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
|
@@ -14661,35 +14618,6 @@
|
|
|
14661
14618
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
|
|
14662
14619
|
"integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
|
|
14663
14620
|
},
|
|
14664
|
-
"node_modules/redux-toolkit": {
|
|
14665
|
-
"version": "1.1.2",
|
|
14666
|
-
"resolved": "https://registry.npmjs.org/redux-toolkit/-/redux-toolkit-1.1.2.tgz",
|
|
14667
|
-
"integrity": "sha1-99yID+oTtIBChLT+AHLvDnpVUv8=",
|
|
14668
|
-
"dependencies": {
|
|
14669
|
-
"debug": "^2.2.0",
|
|
14670
|
-
"flux-standard-action": "^0.6.0",
|
|
14671
|
-
"invariant": "^2.1.1",
|
|
14672
|
-
"lodash": "^3.10.1"
|
|
14673
|
-
}
|
|
14674
|
-
},
|
|
14675
|
-
"node_modules/redux-toolkit/node_modules/debug": {
|
|
14676
|
-
"version": "2.6.9",
|
|
14677
|
-
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
|
14678
|
-
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
|
14679
|
-
"dependencies": {
|
|
14680
|
-
"ms": "2.0.0"
|
|
14681
|
-
}
|
|
14682
|
-
},
|
|
14683
|
-
"node_modules/redux-toolkit/node_modules/lodash": {
|
|
14684
|
-
"version": "3.10.1",
|
|
14685
|
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
|
14686
|
-
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
|
|
14687
|
-
},
|
|
14688
|
-
"node_modules/redux-toolkit/node_modules/ms": {
|
|
14689
|
-
"version": "2.0.0",
|
|
14690
|
-
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
|
14691
|
-
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
|
14692
|
-
},
|
|
14693
14621
|
"node_modules/regenerate": {
|
|
14694
14622
|
"version": "1.4.2",
|
|
14695
14623
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
|
@@ -25225,14 +25153,6 @@
|
|
|
25225
25153
|
"readable-stream": "^2.3.6"
|
|
25226
25154
|
}
|
|
25227
25155
|
},
|
|
25228
|
-
"flux-standard-action": {
|
|
25229
|
-
"version": "0.6.1",
|
|
25230
|
-
"resolved": "https://registry.npmjs.org/flux-standard-action/-/flux-standard-action-0.6.1.tgz",
|
|
25231
|
-
"integrity": "sha1-bzQhG5SDTqHDzDD056+tPQ+/caI=",
|
|
25232
|
-
"requires": {
|
|
25233
|
-
"lodash.isplainobject": "^3.2.0"
|
|
25234
|
-
}
|
|
25235
|
-
},
|
|
25236
25156
|
"follow-redirects": {
|
|
25237
25157
|
"version": "1.13.2",
|
|
25238
25158
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
|
|
@@ -26147,14 +26067,6 @@
|
|
|
26147
26067
|
"side-channel": "^1.0.4"
|
|
26148
26068
|
}
|
|
26149
26069
|
},
|
|
26150
|
-
"invariant": {
|
|
26151
|
-
"version": "2.2.4",
|
|
26152
|
-
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
|
26153
|
-
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
|
26154
|
-
"requires": {
|
|
26155
|
-
"loose-envify": "^1.0.0"
|
|
26156
|
-
}
|
|
26157
|
-
},
|
|
26158
26070
|
"ip": {
|
|
26159
26071
|
"version": "1.1.5",
|
|
26160
26072
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
|
@@ -27332,50 +27244,16 @@
|
|
|
27332
27244
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
27333
27245
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
|
27334
27246
|
},
|
|
27335
|
-
"lodash._basefor": {
|
|
27336
|
-
"version": "3.0.3",
|
|
27337
|
-
"resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz",
|
|
27338
|
-
"integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI="
|
|
27339
|
-
},
|
|
27340
27247
|
"lodash._reinterpolate": {
|
|
27341
27248
|
"version": "3.0.0",
|
|
27342
27249
|
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
|
27343
27250
|
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
|
27344
27251
|
},
|
|
27345
|
-
"lodash.isarguments": {
|
|
27346
|
-
"version": "3.1.0",
|
|
27347
|
-
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
|
27348
|
-
"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
|
|
27349
|
-
},
|
|
27350
|
-
"lodash.isarray": {
|
|
27351
|
-
"version": "3.0.4",
|
|
27352
|
-
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
|
|
27353
|
-
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
|
|
27354
|
-
},
|
|
27355
27252
|
"lodash.isequalwith": {
|
|
27356
27253
|
"version": "4.4.0",
|
|
27357
27254
|
"resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz",
|
|
27358
27255
|
"integrity": "sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA="
|
|
27359
27256
|
},
|
|
27360
|
-
"lodash.isplainobject": {
|
|
27361
|
-
"version": "3.2.0",
|
|
27362
|
-
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz",
|
|
27363
|
-
"integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=",
|
|
27364
|
-
"requires": {
|
|
27365
|
-
"lodash._basefor": "^3.0.0",
|
|
27366
|
-
"lodash.isarguments": "^3.0.0",
|
|
27367
|
-
"lodash.keysin": "^3.0.0"
|
|
27368
|
-
}
|
|
27369
|
-
},
|
|
27370
|
-
"lodash.keysin": {
|
|
27371
|
-
"version": "3.0.8",
|
|
27372
|
-
"resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz",
|
|
27373
|
-
"integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=",
|
|
27374
|
-
"requires": {
|
|
27375
|
-
"lodash.isarguments": "^3.0.0",
|
|
27376
|
-
"lodash.isarray": "^3.0.0"
|
|
27377
|
-
}
|
|
27378
|
-
},
|
|
27379
27257
|
"lodash.memoize": {
|
|
27380
27258
|
"version": "4.1.2",
|
|
27381
27259
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
|
@@ -30286,37 +30164,6 @@
|
|
|
30286
30164
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
|
|
30287
30165
|
"integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
|
|
30288
30166
|
},
|
|
30289
|
-
"redux-toolkit": {
|
|
30290
|
-
"version": "1.1.2",
|
|
30291
|
-
"resolved": "https://registry.npmjs.org/redux-toolkit/-/redux-toolkit-1.1.2.tgz",
|
|
30292
|
-
"integrity": "sha1-99yID+oTtIBChLT+AHLvDnpVUv8=",
|
|
30293
|
-
"requires": {
|
|
30294
|
-
"debug": "^2.2.0",
|
|
30295
|
-
"flux-standard-action": "^0.6.0",
|
|
30296
|
-
"invariant": "^2.1.1",
|
|
30297
|
-
"lodash": "^3.10.1"
|
|
30298
|
-
},
|
|
30299
|
-
"dependencies": {
|
|
30300
|
-
"debug": {
|
|
30301
|
-
"version": "2.6.9",
|
|
30302
|
-
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
|
30303
|
-
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
|
30304
|
-
"requires": {
|
|
30305
|
-
"ms": "2.0.0"
|
|
30306
|
-
}
|
|
30307
|
-
},
|
|
30308
|
-
"lodash": {
|
|
30309
|
-
"version": "3.10.1",
|
|
30310
|
-
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
|
30311
|
-
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
|
|
30312
|
-
},
|
|
30313
|
-
"ms": {
|
|
30314
|
-
"version": "2.0.0",
|
|
30315
|
-
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
|
30316
|
-
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
|
30317
|
-
}
|
|
30318
|
-
}
|
|
30319
|
-
},
|
|
30320
30167
|
"regenerate": {
|
|
30321
30168
|
"version": "1.4.2",
|
|
30322
30169
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
|
@@ -30846,8 +30693,16 @@
|
|
|
30846
30693
|
"saga-toolkit": {
|
|
30847
30694
|
"version": "file:..",
|
|
30848
30695
|
"requires": {
|
|
30696
|
+
"@babel/cli": "^7.16.8",
|
|
30697
|
+
"@babel/core": "^7.16.12",
|
|
30698
|
+
"@babel/node": "^7.16.8",
|
|
30699
|
+
"@babel/preset-env": "^7.16.11",
|
|
30700
|
+
"@reduxjs/toolkit": "^1.7.2",
|
|
30701
|
+
"babel-jest": "^27.4.6",
|
|
30702
|
+
"jest": "^27.4.7",
|
|
30703
|
+
"redux": "^4.1.2",
|
|
30849
30704
|
"redux-saga": "^1.1.3",
|
|
30850
|
-
"redux-
|
|
30705
|
+
"redux-saga-test-plan": "^4.0.4"
|
|
30851
30706
|
}
|
|
30852
30707
|
},
|
|
30853
30708
|
"sane": {
|
package/example/src/App.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { unwrapResult } from '@reduxjs/toolkit'
|
|
1
2
|
import { useApp, useAppStart } from './hooks'
|
|
2
3
|
import logo from './logo.svg';
|
|
3
4
|
import './App.css';
|
|
4
5
|
|
|
5
6
|
function App() {
|
|
6
|
-
const { started, click, fetchThings } = useApp()
|
|
7
|
+
const { started, click, fetchThings, fetchThingsDebounce } = useApp()
|
|
7
8
|
|
|
8
9
|
const handleClick = async () => {
|
|
9
10
|
try {
|
|
@@ -23,6 +24,15 @@ function App() {
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
const handleFetchThingsDebounce = async () => {
|
|
28
|
+
try {
|
|
29
|
+
const result = unwrapResult(await fetchThingsDebounce(false))
|
|
30
|
+
console.log('fetchThingsDebounce SUCCESS', result)
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.log('fetchThingsDebounce ERROR', error)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
useAppStart()
|
|
27
37
|
|
|
28
38
|
return (
|
|
@@ -34,6 +44,7 @@ function App() {
|
|
|
34
44
|
</p>
|
|
35
45
|
<button onClick={handleClick}>click</button>
|
|
36
46
|
<button onClick={handleFetchThings}>fetchThings</button>
|
|
47
|
+
<button onClick={handleFetchThingsDebounce}>fetchThingsDebounce</button>
|
|
37
48
|
<a
|
|
38
49
|
className="App-link"
|
|
39
50
|
href="https://reactjs.org"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAsyncThunk, unwrapResult } from '@reduxjs/toolkit'
|
|
2
|
-
import { put, takeEvery } from '@redux-saga/core/effects'
|
|
2
|
+
import { put, take, fork, takeEvery, cancel } from '@redux-saga/core/effects'
|
|
3
3
|
import createDeferred from '@redux-saga/deferred'
|
|
4
4
|
|
|
5
5
|
const requests = {}
|
|
@@ -49,8 +49,8 @@ const cleanup = requestId => {
|
|
|
49
49
|
delete requests[requestId]
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function* getRequest(
|
|
53
|
-
const { requestId } = action.meta
|
|
52
|
+
function* getRequest(requestId) {
|
|
53
|
+
// const { requestId } = action.meta
|
|
54
54
|
const request = requests[requestId]
|
|
55
55
|
|
|
56
56
|
if (!request) {
|
|
@@ -64,12 +64,13 @@ function* getRequest(action) {
|
|
|
64
64
|
|
|
65
65
|
const wrap = saga => function* (action, ...rest) {
|
|
66
66
|
const { requestId } = action.meta
|
|
67
|
-
const request = yield getRequest(
|
|
67
|
+
const request = yield getRequest(requestId)
|
|
68
68
|
const deferred = request.deferred
|
|
69
69
|
|
|
70
70
|
try {
|
|
71
71
|
deferred.resolve(yield saga(action, ...rest))
|
|
72
72
|
} catch (error) {
|
|
73
|
+
console.log(error)
|
|
73
74
|
deferred.reject(error)
|
|
74
75
|
} finally {
|
|
75
76
|
cleanup(requestId)
|
|
@@ -82,16 +83,22 @@ export function takeEveryAsync(pattern, saga, ...args) {
|
|
|
82
83
|
|
|
83
84
|
export function takeLatestAsync(pattern, saga, ...args) {
|
|
84
85
|
let deferred
|
|
86
|
+
const tasks = {}
|
|
85
87
|
|
|
86
88
|
function* wrapper(action, ...rest) {
|
|
87
89
|
if (deferred) {
|
|
88
90
|
const lastRequestId = yield deferred.promise
|
|
91
|
+
const request = yield getRequest(lastRequestId)
|
|
92
|
+
|
|
93
|
+
request.abort()
|
|
94
|
+
|
|
95
|
+
const task = yield tasks[lastRequestId].promise
|
|
89
96
|
|
|
90
|
-
|
|
97
|
+
yield cancel(task)
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
deferred = createDeferred()
|
|
94
|
-
const { requestId } = yield getRequest(action)
|
|
101
|
+
const { requestId } = yield getRequest(action.meta.requestId)
|
|
95
102
|
|
|
96
103
|
deferred.resolve(requestId)
|
|
97
104
|
|
|
@@ -100,6 +107,15 @@ export function takeLatestAsync(pattern, saga, ...args) {
|
|
|
100
107
|
deferred = null
|
|
101
108
|
}
|
|
102
109
|
|
|
110
|
+
const takeEvery = (patternOrChannel, saga, ...args) => fork(function* () {
|
|
111
|
+
while (true) {
|
|
112
|
+
const action = yield take(patternOrChannel)
|
|
113
|
+
const { requestId } = action.meta
|
|
114
|
+
tasks[requestId] = createDeferred()
|
|
115
|
+
tasks[requestId].resolve(yield fork(saga, ...args.concat(action)))
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
103
119
|
return takeEvery(pattern, wrapper, ...args)
|
|
104
120
|
}
|
|
105
121
|
|
|
@@ -110,7 +126,7 @@ export function takeAggregateAsync(pattern, saga, ...args) {
|
|
|
110
126
|
const { requestId } = action.meta
|
|
111
127
|
|
|
112
128
|
if (deferred) {
|
|
113
|
-
const request = yield getRequest(
|
|
129
|
+
const request = yield getRequest(requestId)
|
|
114
130
|
const { resolve, reject } = request.deferred
|
|
115
131
|
const { promise } = yield deferred.promise
|
|
116
132
|
|
|
@@ -120,7 +136,7 @@ export function takeAggregateAsync(pattern, saga, ...args) {
|
|
|
120
136
|
.catch(() => { })
|
|
121
137
|
} else {
|
|
122
138
|
deferred = createDeferred()
|
|
123
|
-
const request = yield getRequest(
|
|
139
|
+
const request = yield getRequest(requestId)
|
|
124
140
|
const { promise } = request.deferred
|
|
125
141
|
|
|
126
142
|
yield wrap(saga)(action, ...rest)
|
package/example/src/sagas.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { call, delay, put, select, takeEvery } from 'redux-saga/effects'
|
|
1
|
+
import { call, cancelled, delay, put, select, takeEvery } from 'redux-saga/effects'
|
|
2
2
|
import { LOCATION_CHANGE } from 'connected-react-router'
|
|
3
3
|
import {
|
|
4
4
|
takeEveryAsync,
|
|
@@ -59,6 +59,23 @@ function* fetchThings({ meta }) {
|
|
|
59
59
|
return result
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
function* fetchThingsDebounce({ meta }) {
|
|
63
|
+
try {
|
|
64
|
+
yield delay(1000)
|
|
65
|
+
|
|
66
|
+
console.log('STILL RUNNING', meta.requestId)
|
|
67
|
+
} finally {
|
|
68
|
+
if (yield cancelled()) {
|
|
69
|
+
console.log('CANCELLED', meta.requestId)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// const result = yield call(() => hyperSuperApi(true))
|
|
74
|
+
|
|
75
|
+
// return result
|
|
76
|
+
return 'shite'
|
|
77
|
+
}
|
|
78
|
+
|
|
62
79
|
function* click() {
|
|
63
80
|
try {
|
|
64
81
|
yield putAsync(actions.fetchThings(false))
|
|
@@ -71,6 +88,7 @@ export default [
|
|
|
71
88
|
takeEveryAsync(actions.start.pending.toString(), appStart),
|
|
72
89
|
// takeAggregateAsync(actions.fetchThings.pending.toString(), fetchThings),
|
|
73
90
|
takeEveryAsync(actions.fetchThings.pending.toString(), fetchThings),
|
|
91
|
+
takeLatestAsync(actions.fetchThingsDebounce.pending.toString(), fetchThingsDebounce),
|
|
74
92
|
takeEvery(actions.click.type.toString(), click),
|
|
75
93
|
takeEvery(LOCATION_CHANGE, locationChange),
|
|
76
94
|
]
|
package/example/src/slice.js
CHANGED
|
@@ -10,6 +10,7 @@ const initialState = {
|
|
|
10
10
|
|
|
11
11
|
export const start = createSagaAction(`${name}/start`)
|
|
12
12
|
export const fetchThings = createSagaAction(`${name}/fetchThings`)
|
|
13
|
+
export const fetchThingsDebounce = createSagaAction(`${name}/fetchThingsDebounce`)
|
|
13
14
|
export const click = createAction(`${name}/click`)
|
|
14
15
|
|
|
15
16
|
const slice = createSlice({
|
|
@@ -15,7 +15,7 @@ const createStore = ({ history }) => {
|
|
|
15
15
|
sagaMiddleware,
|
|
16
16
|
],
|
|
17
17
|
// middleware: getDefaultMiddleware => getDefaultMiddleware().concat(sagaMiddleware),
|
|
18
|
-
devTools:
|
|
18
|
+
devTools: true,
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
sagaMiddleware.run(function* () {
|
package/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
exports
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createSagaAction = void 0;
|
|
7
|
+
exports.putAsync = putAsync;
|
|
8
|
+
exports.takeAggregateAsync = takeAggregateAsync;
|
|
4
9
|
exports.takeEveryAsync = takeEveryAsync;
|
|
5
10
|
exports.takeLatestAsync = takeLatestAsync;
|
|
6
|
-
exports.takeAggregateAsync = takeAggregateAsync;
|
|
7
|
-
exports.putAsync = putAsync;
|
|
8
|
-
exports.createSagaAction = void 0;
|
|
9
11
|
|
|
10
12
|
var _toolkit = require("@reduxjs/toolkit");
|
|
11
13
|
|
|
@@ -62,10 +64,8 @@ const cleanup = requestId => {
|
|
|
62
64
|
delete requests[requestId];
|
|
63
65
|
};
|
|
64
66
|
|
|
65
|
-
function* getRequest(
|
|
66
|
-
const {
|
|
67
|
-
requestId
|
|
68
|
-
} = action.meta;
|
|
67
|
+
function* getRequest(requestId) {
|
|
68
|
+
// const { requestId } = action.meta
|
|
69
69
|
const request = requests[requestId];
|
|
70
70
|
|
|
71
71
|
if (!request) {
|
|
@@ -83,12 +83,13 @@ const wrap = saga => function* (action, ...rest) {
|
|
|
83
83
|
const {
|
|
84
84
|
requestId
|
|
85
85
|
} = action.meta;
|
|
86
|
-
const request = yield getRequest(
|
|
86
|
+
const request = yield getRequest(requestId);
|
|
87
87
|
const deferred = request.deferred;
|
|
88
88
|
|
|
89
89
|
try {
|
|
90
90
|
deferred.resolve(yield saga(action, ...rest));
|
|
91
91
|
} catch (error) {
|
|
92
|
+
console.log(error);
|
|
92
93
|
deferred.reject(error);
|
|
93
94
|
} finally {
|
|
94
95
|
cleanup(requestId);
|
|
@@ -100,24 +101,39 @@ function takeEveryAsync(pattern, saga, ...args) {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
function takeLatestAsync(pattern, saga, ...args) {
|
|
104
|
+
const tasks = {};
|
|
103
105
|
let deferred;
|
|
104
106
|
|
|
105
107
|
function* wrapper(action, ...rest) {
|
|
106
108
|
if (deferred) {
|
|
107
109
|
const lastRequestId = yield deferred.promise;
|
|
108
|
-
|
|
110
|
+
const request = yield getRequest(lastRequestId);
|
|
111
|
+
request.abort();
|
|
112
|
+
const task = yield tasks[lastRequestId].promise;
|
|
113
|
+
yield (0, _effects.cancel)(task);
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
deferred = (0, _deferred.default)();
|
|
112
117
|
const {
|
|
113
118
|
requestId
|
|
114
|
-
} = yield getRequest(action);
|
|
119
|
+
} = yield getRequest(action.meta.requestId);
|
|
115
120
|
deferred.resolve(requestId);
|
|
116
121
|
yield wrap(saga)(action, ...rest);
|
|
117
122
|
deferred = null;
|
|
118
123
|
}
|
|
119
124
|
|
|
120
|
-
|
|
125
|
+
const takeEvery = (patternOrChannel, saga, ...args) => (0, _effects.fork)(function* () {
|
|
126
|
+
while (true) {
|
|
127
|
+
const action = yield (0, _effects.take)(patternOrChannel);
|
|
128
|
+
const {
|
|
129
|
+
requestId
|
|
130
|
+
} = action.meta;
|
|
131
|
+
tasks[requestId] = (0, _deferred.default)();
|
|
132
|
+
tasks[requestId].resolve(yield (0, _effects.fork)(saga, ...args.concat(action)));
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return takeEvery(pattern, wrapper, ...args);
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
function takeAggregateAsync(pattern, saga, ...args) {
|
|
@@ -129,7 +145,7 @@ function takeAggregateAsync(pattern, saga, ...args) {
|
|
|
129
145
|
} = action.meta;
|
|
130
146
|
|
|
131
147
|
if (deferred) {
|
|
132
|
-
const request = yield getRequest(
|
|
148
|
+
const request = yield getRequest(requestId);
|
|
133
149
|
const {
|
|
134
150
|
resolve,
|
|
135
151
|
reject
|
|
@@ -140,7 +156,7 @@ function takeAggregateAsync(pattern, saga, ...args) {
|
|
|
140
156
|
promise.then(resolve, reject).finally(() => cleanup(requestId)).catch(() => {});
|
|
141
157
|
} else {
|
|
142
158
|
deferred = (0, _deferred.default)();
|
|
143
|
-
const request = yield getRequest(
|
|
159
|
+
const request = yield getRequest(requestId);
|
|
144
160
|
const {
|
|
145
161
|
promise
|
|
146
162
|
} = request.deferred;
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "saga-toolkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "An extension for redux-toolkit that allows sagas to resolve async thunk actions.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"build": "./node_modules/.bin/babel sagaToolkit.js --out-file index.js",
|
|
7
8
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
9
|
},
|
|
9
10
|
"repository": {
|
|
@@ -24,8 +25,10 @@
|
|
|
24
25
|
"url": "https://github.com/janoist1/saga-toolkit/issues"
|
|
25
26
|
},
|
|
26
27
|
"homepage": "https://github.com/janoist1/saga-toolkit#readme",
|
|
27
|
-
"
|
|
28
|
-
"@
|
|
29
|
-
"
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@babel/cli": "^7.16.8",
|
|
30
|
+
"@babel/core": "^7.16.12",
|
|
31
|
+
"@babel/node": "^7.16.8",
|
|
32
|
+
"@babel/preset-env": "^7.16.11"
|
|
30
33
|
}
|
|
31
34
|
}
|
package/sagaToolkit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAsyncThunk, unwrapResult } from '@reduxjs/toolkit'
|
|
2
|
-
import { put, takeEvery } from '@redux-saga/core/effects'
|
|
2
|
+
import { put, take, fork, takeEvery, cancel } from '@redux-saga/core/effects'
|
|
3
3
|
import createDeferred from '@redux-saga/deferred'
|
|
4
4
|
|
|
5
5
|
const requests = {}
|
|
@@ -49,8 +49,8 @@ const cleanup = requestId => {
|
|
|
49
49
|
delete requests[requestId]
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function* getRequest(
|
|
53
|
-
const { requestId } = action.meta
|
|
52
|
+
function* getRequest(requestId) {
|
|
53
|
+
// const { requestId } = action.meta
|
|
54
54
|
const request = requests[requestId]
|
|
55
55
|
|
|
56
56
|
if (!request) {
|
|
@@ -64,12 +64,13 @@ function* getRequest(action) {
|
|
|
64
64
|
|
|
65
65
|
const wrap = saga => function* (action, ...rest) {
|
|
66
66
|
const { requestId } = action.meta
|
|
67
|
-
const request = yield getRequest(
|
|
67
|
+
const request = yield getRequest(requestId)
|
|
68
68
|
const deferred = request.deferred
|
|
69
69
|
|
|
70
70
|
try {
|
|
71
71
|
deferred.resolve(yield saga(action, ...rest))
|
|
72
72
|
} catch (error) {
|
|
73
|
+
console.log(error)
|
|
73
74
|
deferred.reject(error)
|
|
74
75
|
} finally {
|
|
75
76
|
cleanup(requestId)
|
|
@@ -81,17 +82,23 @@ export function takeEveryAsync(pattern, saga, ...args) {
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
export function takeLatestAsync(pattern, saga, ...args) {
|
|
85
|
+
const tasks = {}
|
|
84
86
|
let deferred
|
|
85
87
|
|
|
86
88
|
function* wrapper(action, ...rest) {
|
|
87
89
|
if (deferred) {
|
|
88
90
|
const lastRequestId = yield deferred.promise
|
|
91
|
+
const request = yield getRequest(lastRequestId)
|
|
92
|
+
|
|
93
|
+
request.abort()
|
|
94
|
+
|
|
95
|
+
const task = yield tasks[lastRequestId].promise
|
|
89
96
|
|
|
90
|
-
|
|
97
|
+
yield cancel(task)
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
deferred = createDeferred()
|
|
94
|
-
const { requestId } = yield getRequest(action)
|
|
101
|
+
const { requestId } = yield getRequest(action.meta.requestId)
|
|
95
102
|
|
|
96
103
|
deferred.resolve(requestId)
|
|
97
104
|
|
|
@@ -100,6 +107,15 @@ export function takeLatestAsync(pattern, saga, ...args) {
|
|
|
100
107
|
deferred = null
|
|
101
108
|
}
|
|
102
109
|
|
|
110
|
+
const takeEvery = (patternOrChannel, saga, ...args) => fork(function* () {
|
|
111
|
+
while (true) {
|
|
112
|
+
const action = yield take(patternOrChannel)
|
|
113
|
+
const { requestId } = action.meta
|
|
114
|
+
tasks[requestId] = createDeferred()
|
|
115
|
+
tasks[requestId].resolve(yield fork(saga, ...args.concat(action)))
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
103
119
|
return takeEvery(pattern, wrapper, ...args)
|
|
104
120
|
}
|
|
105
121
|
|
|
@@ -110,7 +126,7 @@ export function takeAggregateAsync(pattern, saga, ...args) {
|
|
|
110
126
|
const { requestId } = action.meta
|
|
111
127
|
|
|
112
128
|
if (deferred) {
|
|
113
|
-
const request = yield getRequest(
|
|
129
|
+
const request = yield getRequest(requestId)
|
|
114
130
|
const { resolve, reject } = request.deferred
|
|
115
131
|
const { promise } = yield deferred.promise
|
|
116
132
|
|
|
@@ -120,7 +136,7 @@ export function takeAggregateAsync(pattern, saga, ...args) {
|
|
|
120
136
|
.catch(() => { })
|
|
121
137
|
} else {
|
|
122
138
|
deferred = createDeferred()
|
|
123
|
-
const request = yield getRequest(
|
|
139
|
+
const request = yield getRequest(requestId)
|
|
124
140
|
const { promise } = request.deferred
|
|
125
141
|
|
|
126
142
|
yield wrap(saga)(action, ...rest)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { combineReducers } from 'redux'
|
|
2
|
+
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
|
|
3
|
+
import createSagaMiddleware from 'redux-saga'
|
|
4
|
+
import { all } from 'redux-saga/effects'
|
|
5
|
+
|
|
6
|
+
export default ({ initialState, reducers, sagas }) => {
|
|
7
|
+
const sagaMiddleware = createSagaMiddleware()
|
|
8
|
+
const store = configureStore({
|
|
9
|
+
reducer: combineReducers(reducers),
|
|
10
|
+
middleware: [...getDefaultMiddleware(), sagaMiddleware],
|
|
11
|
+
devTools: false,
|
|
12
|
+
})
|
|
13
|
+
// const store = createStore(
|
|
14
|
+
// combineReducers(reducers),
|
|
15
|
+
// initialState,
|
|
16
|
+
// applyMiddleware(sagaMiddleware)
|
|
17
|
+
// )
|
|
18
|
+
|
|
19
|
+
sagaMiddleware.run(function* () {
|
|
20
|
+
yield all(sagas)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return store
|
|
24
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { put } from 'redux-saga/effects'
|
|
2
|
+
import { createSlice } from '@reduxjs/toolkit'
|
|
3
|
+
import { expectSaga, testSaga } from 'redux-saga-test-plan'
|
|
4
|
+
import createStore from './createStore'
|
|
5
|
+
import { createSagaAction, takeEveryAsync } from '../sagaToolkit'
|
|
6
|
+
|
|
7
|
+
const initialState = {
|
|
8
|
+
test: null,
|
|
9
|
+
testAsync: null,
|
|
10
|
+
error: null,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const testAsyncAction = createSagaAction('testSlice/testAsyncAction')
|
|
14
|
+
|
|
15
|
+
const slice = createSlice({
|
|
16
|
+
name: 'testSlice',
|
|
17
|
+
initialState,
|
|
18
|
+
reducers: {
|
|
19
|
+
testAction: (state, action) => ({ test: action.payload }),
|
|
20
|
+
},
|
|
21
|
+
extraReducers: {
|
|
22
|
+
[testAsyncAction.pending]: (state, action) => ({
|
|
23
|
+
...state,
|
|
24
|
+
test: action.payload,
|
|
25
|
+
}),
|
|
26
|
+
[testAsyncAction.resolved]: (state, action) => ({
|
|
27
|
+
...state,
|
|
28
|
+
testAsync: 'action.meta.args',
|
|
29
|
+
}),
|
|
30
|
+
[testAsyncAction.rejected]: (state, action) => ({
|
|
31
|
+
...state,
|
|
32
|
+
test: action.payload,
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const { testAction } = slice.actions
|
|
38
|
+
|
|
39
|
+
function* saga() {
|
|
40
|
+
yield put(testAction('testing'))
|
|
41
|
+
|
|
42
|
+
return 'resolved value'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
test('testing sync', () => {
|
|
46
|
+
const reducers = { slice: slice.reducer }
|
|
47
|
+
const sagas = [takeEveryAsync(testAsyncAction.pending, saga)]
|
|
48
|
+
const store = createStore({ initialState, reducers, sagas })
|
|
49
|
+
|
|
50
|
+
store.dispatch(testAction('testing'))
|
|
51
|
+
|
|
52
|
+
const state = store.getState()
|
|
53
|
+
|
|
54
|
+
expect(state).toEqual({
|
|
55
|
+
slice: { test: 'testing' },
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('testing async', () => {
|
|
60
|
+
return expectSaga(saga)
|
|
61
|
+
.withReducer(slice.reducer)
|
|
62
|
+
.hasFinalState({
|
|
63
|
+
test: 'testing',
|
|
64
|
+
testAsync: 'testing async',
|
|
65
|
+
})
|
|
66
|
+
.run()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('testing async 2', () => {
|
|
70
|
+
testSaga(function *() {
|
|
71
|
+
yield takeEveryAsync(testAsyncAction.pending, saga)
|
|
72
|
+
}, 40, 2)
|
|
73
|
+
// advance saga with `next()`
|
|
74
|
+
.next()
|
|
75
|
+
|
|
76
|
+
// assert that the saga yields `take` with `'HELLO'` as type
|
|
77
|
+
// .take('HELLO')
|
|
78
|
+
|
|
79
|
+
// pass back in a value to a saga after it yields
|
|
80
|
+
// .next(action)
|
|
81
|
+
|
|
82
|
+
// assert that the saga yields `put` with the expected action
|
|
83
|
+
.put(testAction('testing'))
|
|
84
|
+
|
|
85
|
+
.next()
|
|
86
|
+
|
|
87
|
+
// assert that the saga yields a `call` to `identity` with
|
|
88
|
+
// the `action` argument
|
|
89
|
+
// .call(identity, action)
|
|
90
|
+
|
|
91
|
+
.next()
|
|
92
|
+
|
|
93
|
+
// assert that the saga is finished
|
|
94
|
+
.isDone();
|
|
95
|
+
})
|
package/example/src/App.test.js
DELETED