@quenty/rx 5.2.0 → 6.0.0
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/CHANGELOG.md +11 -0
- package/package.json +2 -2
- package/src/Shared/Rx.lua +200 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [6.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rx@5.2.0...@quenty/rx@6.0.0) (2022-08-14)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add Rx.share, Rx.shareReplay and Rx.cache ([6f1268f](https://github.com/Quenty/NevermoreEngine/commit/6f1268f8f70908f04dbebff7f2a267fc24eafc19))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [5.2.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rx@5.1.0...@quenty/rx@5.2.0) (2022-07-31)
|
|
7
18
|
|
|
8
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/rx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Quenty's reactive library for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "dbb62609f980983cc32da90acfef13e30ed41113"
|
|
44
44
|
}
|
package/src/Shared/Rx.lua
CHANGED
|
@@ -307,6 +307,205 @@ function Rx.start(callback)
|
|
|
307
307
|
end
|
|
308
308
|
end
|
|
309
309
|
|
|
310
|
+
--[=[
|
|
311
|
+
Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one Subscriber this Observable will be subscribed and emitting data.
|
|
312
|
+
When all subscribers have unsubscribed it will unsubscribe from the source Observable.
|
|
313
|
+
|
|
314
|
+
https://rxjs.dev/api/operators/share
|
|
315
|
+
|
|
316
|
+
@return (source: Observable) -> Observable
|
|
317
|
+
]=]
|
|
318
|
+
function Rx.share()
|
|
319
|
+
return function(source)
|
|
320
|
+
local shareMaid = Maid.new()
|
|
321
|
+
local subs = {}
|
|
322
|
+
|
|
323
|
+
local lastFail = UNSET_VALUE
|
|
324
|
+
local lastComplete = UNSET_VALUE
|
|
325
|
+
|
|
326
|
+
local function connectToSourceIfNeeded()
|
|
327
|
+
if not shareMaid._currentSub then
|
|
328
|
+
lastFail = UNSET_VALUE
|
|
329
|
+
lastComplete = UNSET_VALUE
|
|
330
|
+
|
|
331
|
+
shareMaid._currentSub = source:Subscribe(function(...)
|
|
332
|
+
for _, sub in pairs(subs) do
|
|
333
|
+
sub:Fire(...)
|
|
334
|
+
end
|
|
335
|
+
end, function(...)
|
|
336
|
+
lastFail = table.pack(...)
|
|
337
|
+
for _, sub in pairs(subs) do
|
|
338
|
+
sub:Fail(...)
|
|
339
|
+
end
|
|
340
|
+
end, function(...)
|
|
341
|
+
lastComplete = table.pack(...)
|
|
342
|
+
for _, sub in pairs(subs) do
|
|
343
|
+
sub:Complete(...)
|
|
344
|
+
end
|
|
345
|
+
end)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
local function disconnectFromSource()
|
|
350
|
+
shareMaid._currentSub = nil
|
|
351
|
+
|
|
352
|
+
lastFail = UNSET_VALUE
|
|
353
|
+
lastComplete = UNSET_VALUE
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
assert(Observable.isObservable(source), "Bad observable")
|
|
357
|
+
|
|
358
|
+
return Observable.new(function(sub)
|
|
359
|
+
if lastFail ~= UNSET_VALUE then
|
|
360
|
+
sub:Fail(table.unpack(lastFail, 1, lastFail.n))
|
|
361
|
+
return
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
if lastComplete ~= UNSET_VALUE then
|
|
365
|
+
sub:Fail(table.unpack(lastComplete, 1, lastComplete.n))
|
|
366
|
+
return
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
table.insert(subs, sub)
|
|
370
|
+
connectToSourceIfNeeded()
|
|
371
|
+
|
|
372
|
+
return function()
|
|
373
|
+
local index = table.find(subs, sub)
|
|
374
|
+
if index then
|
|
375
|
+
table.remove(subs, index)
|
|
376
|
+
|
|
377
|
+
if #subs == 0 then
|
|
378
|
+
disconnectFromSource()
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end)
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
--[=[
|
|
387
|
+
Same as [Rx.share] except it also replays the value
|
|
388
|
+
|
|
389
|
+
@param bufferSize number -- Number of entries to cache
|
|
390
|
+
@param windowTimeSeconds number -- Time
|
|
391
|
+
@return (source: Observable) -> Observable
|
|
392
|
+
]=]
|
|
393
|
+
function Rx.shareReplay(bufferSize, windowTimeSeconds)
|
|
394
|
+
assert(type(bufferSize) == "number" or bufferSize == nil, "Bad bufferSize")
|
|
395
|
+
assert(type(windowTimeSeconds) == "number" or windowTimeSeconds == nil, "Bad windowTimeSeconds")
|
|
396
|
+
|
|
397
|
+
bufferSize = bufferSize or math.huge
|
|
398
|
+
windowTimeSeconds = windowTimeSeconds or math.huge
|
|
399
|
+
|
|
400
|
+
return function(source)
|
|
401
|
+
local shareMaid = Maid.new()
|
|
402
|
+
local subs = {}
|
|
403
|
+
|
|
404
|
+
local buffer = {}
|
|
405
|
+
local lastFail = UNSET_VALUE
|
|
406
|
+
local lastComplete = UNSET_VALUE
|
|
407
|
+
|
|
408
|
+
local function getEventsCopy()
|
|
409
|
+
local now = os.clock()
|
|
410
|
+
local events = {}
|
|
411
|
+
|
|
412
|
+
for _, event in pairs(buffer) do
|
|
413
|
+
if (now - event.timestamp) <= windowTimeSeconds then
|
|
414
|
+
table.insert(events, event)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
return events
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
local function connectToSourceIfNeeded()
|
|
422
|
+
if not shareMaid._currentSub then
|
|
423
|
+
buffer = {}
|
|
424
|
+
lastFail = UNSET_VALUE
|
|
425
|
+
lastComplete = UNSET_VALUE
|
|
426
|
+
|
|
427
|
+
shareMaid._currentSub = source:Subscribe(function(...)
|
|
428
|
+
-- TODO: also prune events by timestamp
|
|
429
|
+
|
|
430
|
+
if #buffer + 1 > bufferSize then
|
|
431
|
+
table.remove(buffer, 1) -- O(n), not great.
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
-- Queue before we start
|
|
435
|
+
local event = table.pack(...)
|
|
436
|
+
event.timestamp = os.clock()
|
|
437
|
+
table.insert(buffer, event)
|
|
438
|
+
|
|
439
|
+
for _, sub in pairs(subs) do
|
|
440
|
+
sub:Fire(...)
|
|
441
|
+
end
|
|
442
|
+
end, function(...)
|
|
443
|
+
lastFail = table.pack(...)
|
|
444
|
+
for _, sub in pairs(subs) do
|
|
445
|
+
sub:Fail(...)
|
|
446
|
+
end
|
|
447
|
+
end, function(...)
|
|
448
|
+
lastComplete = table.pack(...)
|
|
449
|
+
for _, sub in pairs(subs) do
|
|
450
|
+
sub:Complete(...)
|
|
451
|
+
end
|
|
452
|
+
end)
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
local function disconnectFromSource()
|
|
457
|
+
shareMaid._currentSub = nil
|
|
458
|
+
|
|
459
|
+
buffer = {}
|
|
460
|
+
lastFail = UNSET_VALUE
|
|
461
|
+
lastComplete = UNSET_VALUE
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
assert(Observable.isObservable(source), "Bad observable")
|
|
465
|
+
|
|
466
|
+
return Observable.new(function(sub)
|
|
467
|
+
if lastFail ~= UNSET_VALUE then
|
|
468
|
+
sub:Fail(table.unpack(lastFail, 1, lastFail.n))
|
|
469
|
+
return
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
if lastComplete ~= UNSET_VALUE then
|
|
473
|
+
sub:Fail(table.unpack(lastComplete, 1, lastComplete.n))
|
|
474
|
+
return
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
table.insert(subs, sub)
|
|
478
|
+
|
|
479
|
+
-- Firing could lead to re-entrance. Lets just use the buffer as-is.
|
|
480
|
+
for _, item in pairs(getEventsCopy()) do
|
|
481
|
+
sub:Fire(table.unpack(item, 1, item.n))
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
connectToSourceIfNeeded()
|
|
485
|
+
|
|
486
|
+
return function()
|
|
487
|
+
local index = table.find(subs, sub)
|
|
488
|
+
if index then
|
|
489
|
+
table.remove(subs, index)
|
|
490
|
+
|
|
491
|
+
if #subs == 0 then
|
|
492
|
+
disconnectFromSource()
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end)
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
--[=[
|
|
501
|
+
Caches the current value
|
|
502
|
+
|
|
503
|
+
@return (source: Observable) -> Observable
|
|
504
|
+
]=]
|
|
505
|
+
function Rx.cache()
|
|
506
|
+
return Rx.shareReplay(1)
|
|
507
|
+
end
|
|
508
|
+
|
|
310
509
|
--[=[
|
|
311
510
|
Like start, but also from (list!)
|
|
312
511
|
|
|
@@ -1436,7 +1635,7 @@ function Rx.throttleDefer()
|
|
|
1436
1635
|
lastResult = table.pack(...)
|
|
1437
1636
|
|
|
1438
1637
|
-- Queue up our result
|
|
1439
|
-
task.defer(function()
|
|
1638
|
+
maid._currentQueue = task.defer(function()
|
|
1440
1639
|
local current = lastResult
|
|
1441
1640
|
lastResult = nil
|
|
1442
1641
|
|