statebus 7.0.4 → 7.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/{clients.js → client-library.js} +256 -126
- package/extras/tests.js +58 -58
- package/package.json +3 -3
- package/{servers.js → server-library.js} +116 -84
- package/statebus.js +78 -58
package/statebus.js
CHANGED
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
// arrived nested within a bigger object, because we never explicity
|
|
52
52
|
// got those keys. But we don't need to get them now cause we
|
|
53
53
|
// already have them.
|
|
54
|
-
var
|
|
54
|
+
var getterters = 0
|
|
55
55
|
if (!gets_out[key])
|
|
56
|
-
|
|
56
|
+
getterters = bus.route(key, 'getter', key)
|
|
57
57
|
|
|
58
58
|
// Now there might be a new value pubbed onto this bus.
|
|
59
59
|
// Or there might be a pending get.
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
|
|
72
72
|
// Otherwise, we want to make sure that a pub gets called on the
|
|
73
73
|
// handler. If there's a pending get, then it'll get called later.
|
|
74
|
-
// If there was a
|
|
74
|
+
// If there was a getter, then it already got called. Otherwise,
|
|
75
75
|
// let's call it now.
|
|
76
|
-
else if (!pending_gets[key] &&
|
|
76
|
+
else if (!pending_gets[key] && getterters === 0) {
|
|
77
77
|
// TODO: my intuition suggests that we might prefer to delay this
|
|
78
78
|
// .on_set getting called in a setTimeout(f,0), to be consistent
|
|
79
79
|
// with other calls to .on_set.
|
|
@@ -130,8 +130,8 @@
|
|
|
130
130
|
var was_saving = currently_saving
|
|
131
131
|
currently_saving = obj.key
|
|
132
132
|
|
|
133
|
-
// Call the
|
|
134
|
-
var num_handlers = bus.route(obj.key, '
|
|
133
|
+
// Call the setter() handlers!
|
|
134
|
+
var num_handlers = bus.route(obj.key, 'setter', obj, t)
|
|
135
135
|
if (num_handlers === 0) {
|
|
136
136
|
// And fire if there weren't any!
|
|
137
137
|
set.fire(obj, t)
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
currently_saving = was_saving
|
|
144
144
|
}
|
|
145
145
|
// TODO: Here's an alternative. Instead of counting the handlers and
|
|
146
|
-
// seeing if there are zero, I could just make a
|
|
146
|
+
// seeing if there are zero, I could just make a setter handler that
|
|
147
147
|
// is shadowed by other handlers if I can get later handlers to shadow
|
|
148
148
|
// earlier ones.
|
|
149
149
|
}
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
if (obj.key && !changed(obj)) {
|
|
192
192
|
color = grey
|
|
193
193
|
icon = 'x'
|
|
194
|
-
if (t.
|
|
194
|
+
if (t.getter)
|
|
195
195
|
message = (t.m) || 'Got ' + bus + "('"+obj.key+"')"
|
|
196
196
|
if (t.version) message += ' [' + t.version + ']'
|
|
197
197
|
statelog(obj.key, color, icon, message)
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
color = red, icon = '•'
|
|
202
|
-
if (t.
|
|
202
|
+
if (t.getter || pending_gets[obj.key]) {
|
|
203
203
|
color = green
|
|
204
204
|
icon = '^'
|
|
205
205
|
message = add_diff_msg((t.m)||'Got '+bus+"('"+obj.key+"')",
|
|
@@ -409,7 +409,7 @@
|
|
|
409
409
|
clearTimeout(to_be_forgotten[key])
|
|
410
410
|
to_be_forgotten[key] = setTimeout(function () {
|
|
411
411
|
// Send a forget upstream
|
|
412
|
-
bus.route(key, '
|
|
412
|
+
bus.route(key, 'forgetter', key, t)
|
|
413
413
|
|
|
414
414
|
// Delete the cache entry...?
|
|
415
415
|
// delete cache[key]
|
|
@@ -429,8 +429,8 @@
|
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
statelog(key, yellow, 'v', 'Deleting ' + key)
|
|
432
|
-
// Call the
|
|
433
|
-
var handlers_called = bus.route(key, '
|
|
432
|
+
// Call the deleter handlers
|
|
433
|
+
var handlers_called = bus.route(key, 'deleter', key)
|
|
434
434
|
if (handlers_called === 0)
|
|
435
435
|
// And go ahead and delete if there aren't any!
|
|
436
436
|
delete cache[key]
|
|
@@ -445,11 +445,11 @@
|
|
|
445
445
|
// - Add transactions, so you can check permissions, abort a delete,
|
|
446
446
|
// etc.
|
|
447
447
|
// - NOTE: I did a crappy implementation of abort just now above!
|
|
448
|
-
// But it doesn't work if called after the
|
|
448
|
+
// But it doesn't work if called after the deleter handler returns.
|
|
449
449
|
// - Generalize the code across set and del with a "mutate"
|
|
450
450
|
// operation
|
|
451
451
|
//
|
|
452
|
-
// - Right now we fire the
|
|
452
|
+
// - Right now we fire the deleter handlers right here.
|
|
453
453
|
//
|
|
454
454
|
// - Do we want to batch them up and fire them later?
|
|
455
455
|
// e.g. we could make a mark_deleted(key) like mark_changed(key)
|
|
@@ -468,7 +468,7 @@
|
|
|
468
468
|
|
|
469
469
|
var version = (t && t.version) || 'dirty-' + new_version()
|
|
470
470
|
|
|
471
|
-
// Find any .
|
|
471
|
+
// Find any .getter, and mark as dirty so that it re-runs
|
|
472
472
|
var found = false
|
|
473
473
|
if (gets_out.hasOwnProperty(key))
|
|
474
474
|
for (var i=0; i<gets_out[key].length; i++) {
|
|
@@ -588,13 +588,21 @@
|
|
|
588
588
|
// ****************
|
|
589
589
|
// Connections
|
|
590
590
|
function subspace (key, params) {
|
|
591
|
-
var methods = {
|
|
592
|
-
on_delete:null,
|
|
591
|
+
var methods = {getter:null, setter:null, on_set:null, on_set_sync:null,
|
|
592
|
+
on_delete:null, deleter:null, forgetter:null}
|
|
593
593
|
|
|
594
594
|
if (params) {
|
|
595
595
|
for (var method in params) {
|
|
596
|
-
console.assert(method in methods)
|
|
597
596
|
var func = params[method]
|
|
597
|
+
var param_names = {get:'getter', set:'setter',
|
|
598
|
+
delete: 'deleter', forget: 'forgetter',
|
|
599
|
+
on_set:'on_set', on_set_sync:'on_set_sync'}
|
|
600
|
+
|
|
601
|
+
// Map it from the API's name to our internal name
|
|
602
|
+
console.assert(param_names[method],
|
|
603
|
+
'Method "' + method + '" is invalid')
|
|
604
|
+
method = param_names[method]
|
|
605
|
+
|
|
598
606
|
autodetect_args(func)
|
|
599
607
|
func.defined = func.defined || []
|
|
600
608
|
func.defined.push({bus, method, key, as: 'handler'})
|
|
@@ -756,8 +764,8 @@
|
|
|
756
764
|
|
|
757
765
|
if (false && !funck.global_funk) {
|
|
758
766
|
// \u26A1
|
|
759
|
-
var event = {'
|
|
760
|
-
'
|
|
767
|
+
var event = {'setter':'set','on_set':'set.fire','getter':'get',
|
|
768
|
+
'deleter':'delete','forgetter':'forget'}[method],
|
|
761
769
|
triggering = funk ? 're-running' : 'initiating'
|
|
762
770
|
console.log(' > a', bus+'.'+event + "('" + (arg.key||arg) + "') is " + triggering
|
|
763
771
|
+'\n ' + funk_name(funck))
|
|
@@ -802,7 +810,8 @@
|
|
|
802
810
|
function key_arg () { return ((typeof arg.key) == 'string') ? arg.key : arg }
|
|
803
811
|
function rest_arg () { return (key_arg()).substr(binding.length-1) }
|
|
804
812
|
function val_arg () {
|
|
805
|
-
console.assert(method === '
|
|
813
|
+
console.assert(method === 'setter' || method === 'on_set' || method === 'on_set_sync',
|
|
814
|
+
'Bad method for val_arg()')
|
|
806
815
|
// Is there a time I am supposed to return bus.cache[arg]? It used to say:
|
|
807
816
|
// arg.key ? arg : bus.cache[arg]
|
|
808
817
|
|
|
@@ -821,9 +830,9 @@
|
|
|
821
830
|
t = clone(t || {})
|
|
822
831
|
|
|
823
832
|
// Add .abort() method
|
|
824
|
-
if (method === '
|
|
833
|
+
if (method === 'setter' || method === 'deleter')
|
|
825
834
|
t.abort = function () {
|
|
826
|
-
var key = method === '
|
|
835
|
+
var key = method === 'setter' ? arg.key : arg
|
|
827
836
|
if (f.loading()) return
|
|
828
837
|
bus.cache[key] = bus.cache[key] || {key: key}
|
|
829
838
|
bus.backup_cache[key] = bus.backup_cache[key] || {key: key}
|
|
@@ -831,34 +840,34 @@
|
|
|
831
840
|
}
|
|
832
841
|
|
|
833
842
|
// Add .done() method
|
|
834
|
-
if (method !== '
|
|
843
|
+
if (method !== 'forgetter')
|
|
835
844
|
t.done = function (o) {
|
|
836
|
-
var key = method === '
|
|
845
|
+
var key = method === 'setter' ? arg.key : arg
|
|
837
846
|
if (func.use_linked_json)
|
|
838
847
|
o = {key, val: o}
|
|
839
848
|
bus.log('We are DONE()ing', method, key, o||arg)
|
|
840
849
|
|
|
841
850
|
// We use a simple (and crappy?) heuristic to know if the
|
|
842
|
-
//
|
|
851
|
+
// setter handler has changed the state: whether the
|
|
843
852
|
// programmer passed (o) to the t.done(o) handler. If
|
|
844
853
|
// not, we assume it hasn't changed. If so, we assume it
|
|
845
854
|
// *has* changed, and thus we change the version of the
|
|
846
855
|
// state. I imagine it would be more accurate to diff
|
|
847
|
-
// from before the
|
|
856
|
+
// from before the setter handler began with when
|
|
848
857
|
// t.done(o) ran.
|
|
849
858
|
//
|
|
850
859
|
// Note: We will likely solve this in the future by
|
|
851
|
-
// preventing .
|
|
860
|
+
// preventing .setter() from changing the incoming state,
|
|
852
861
|
// except through an explicit .revise() function.
|
|
853
862
|
if (o) t.version = new_version()
|
|
854
863
|
|
|
855
|
-
if (method === '
|
|
864
|
+
if (method === 'deleter')
|
|
856
865
|
delete bus.cache[key]
|
|
857
|
-
else if (method === '
|
|
866
|
+
else if (method === 'setter') {
|
|
858
867
|
bus.set.fire(o || arg, t)
|
|
859
868
|
bus.route(key, 'on_set_sync', o || arg, t)
|
|
860
869
|
} else {
|
|
861
|
-
// Now method === '
|
|
870
|
+
// Now method === 'getter'
|
|
862
871
|
o.key = key
|
|
863
872
|
bus.set.fire(o, t)
|
|
864
873
|
// And now reset the version cause it could get called again
|
|
@@ -869,14 +878,20 @@
|
|
|
869
878
|
// Alias .return() to .done(), in case that feels better to you
|
|
870
879
|
t.return = t.done
|
|
871
880
|
|
|
881
|
+
// Prepush Scratch:
|
|
882
|
+
// var prepushed = {}
|
|
883
|
+
// t.prepush = function (key) {
|
|
884
|
+
// prepushed[key] = bus.get(key)
|
|
885
|
+
// }
|
|
886
|
+
|
|
872
887
|
// Alias t.reget() to bus.dirty()
|
|
873
|
-
if (method === '
|
|
888
|
+
if (method === 'setter')
|
|
874
889
|
t.reget = function () { bus.dirty(arg.key) }
|
|
875
890
|
|
|
876
891
|
// Now to call the handler, let's line up the function's special
|
|
877
892
|
// named arguemnts like key, o, t, rest, vars, etc.
|
|
878
893
|
var args = []
|
|
879
|
-
args[0] = (method in {
|
|
894
|
+
args[0] = (method in {setter:1, on_set:1, on_set_sync:1}) ? val_arg() : arg
|
|
880
895
|
args[1] = t
|
|
881
896
|
for (var k in (func.args||{})) {
|
|
882
897
|
switch (k) {
|
|
@@ -907,28 +922,29 @@
|
|
|
907
922
|
// arr[func.args[k]] = <compute_blah(k)>
|
|
908
923
|
|
|
909
924
|
// Trigger done() or abort() by return value
|
|
910
|
-
console.assert(!(result === '
|
|
925
|
+
console.assert(!(result === 'getter' &&
|
|
911
926
|
(result === 'done' || result === 'abort')),
|
|
912
|
-
'Returning "done" or "abort" is not allowed from
|
|
927
|
+
'Returning "done" or "abort" is not allowed from getter handlers')
|
|
928
|
+
|
|
913
929
|
if (result === 'done') t.done()
|
|
914
930
|
if (result === 'abort') t.abort()
|
|
915
931
|
|
|
916
932
|
// For get
|
|
917
933
|
if (func.use_linked_json) {
|
|
918
|
-
if (method === '
|
|
934
|
+
if (method === 'getter' && result !== undefined && !f.loading()) {
|
|
919
935
|
var obj = {key: arg, val: result}
|
|
920
936
|
var new_t = clone(t || {})
|
|
921
|
-
new_t.
|
|
937
|
+
new_t.getter = true
|
|
922
938
|
set.fire(obj, new_t)
|
|
923
939
|
return result
|
|
924
940
|
}
|
|
925
941
|
} else {
|
|
926
|
-
if (method === '
|
|
942
|
+
if (method === 'getter' && result instanceof Object
|
|
927
943
|
&& !f.loading() // Experimental.
|
|
928
944
|
) {
|
|
929
945
|
result.key = arg
|
|
930
946
|
var new_t = clone(t || {})
|
|
931
|
-
new_t.
|
|
947
|
+
new_t.getter = true
|
|
932
948
|
set.fire(result, new_t)
|
|
933
949
|
return result
|
|
934
950
|
}
|
|
@@ -937,29 +953,29 @@
|
|
|
937
953
|
// Set, forget and delete handlers stop re-running once they've
|
|
938
954
|
// completed without anything loading.
|
|
939
955
|
// ... with f.forget()
|
|
940
|
-
if (method !== '
|
|
956
|
+
if (method !== 'getter' && !f.loading())
|
|
941
957
|
f.forget()
|
|
942
958
|
})
|
|
943
959
|
f.proxies_for = func
|
|
944
960
|
f.arg = arg
|
|
945
961
|
f.transaction = t || {}
|
|
946
962
|
|
|
947
|
-
//
|
|
948
|
-
if (method === '
|
|
963
|
+
// getter handlers stop re-running when the key is forgotten
|
|
964
|
+
if (method === 'getter') {
|
|
949
965
|
var key = arg
|
|
950
966
|
function handler_done () {
|
|
951
967
|
f.forget()
|
|
952
|
-
unbind(key, '
|
|
968
|
+
unbind(key, 'forgetter', handler_done)
|
|
953
969
|
}
|
|
954
|
-
bind(key, '
|
|
970
|
+
bind(key, 'forgetter', handler_done)
|
|
955
971
|
|
|
956
972
|
// // Check if it's doubled-up
|
|
957
973
|
// if (gets_out[key])
|
|
958
|
-
// console.error('Two .
|
|
974
|
+
// console.error('Two .getter functions are running on the same key',
|
|
959
975
|
// key+'!', funk_name(funck), funk_name(gets_out[key]))
|
|
960
976
|
|
|
961
977
|
gets_out[key] = gets_out[key] || []
|
|
962
|
-
gets_out[key].push(f) // Record active
|
|
978
|
+
gets_out[key].push(f) // Record active getter handler
|
|
963
979
|
pending_gets[key] = f // Record that the get is pending
|
|
964
980
|
}
|
|
965
981
|
|
|
@@ -979,9 +995,9 @@
|
|
|
979
995
|
for (var i=0; i<handlers.length; i++)
|
|
980
996
|
bus.run_handler(handlers[i].func, method, arg, {t: t, binding: handlers[i].key})
|
|
981
997
|
|
|
982
|
-
// if (method === '
|
|
998
|
+
// if (method === 'getter')
|
|
983
999
|
// console.assert(handlers.length<2,
|
|
984
|
-
// 'Two
|
|
1000
|
+
// 'Two getter functions are registered for the same key '+key,
|
|
985
1001
|
// handlers)
|
|
986
1002
|
return handlers.length
|
|
987
1003
|
}
|
|
@@ -1187,7 +1203,7 @@
|
|
|
1187
1203
|
if (!name) throw 'Uncallback function needs a name'
|
|
1188
1204
|
var watching = {}
|
|
1189
1205
|
var prefix = 'uncallback/' + name
|
|
1190
|
-
bus(prefix + '/*').
|
|
1206
|
+
bus(prefix + '/*').getter = function (key, json) {
|
|
1191
1207
|
var args = json
|
|
1192
1208
|
function cb (err, result) {
|
|
1193
1209
|
if (err) {
|
|
@@ -1212,7 +1228,7 @@
|
|
|
1212
1228
|
}
|
|
1213
1229
|
}
|
|
1214
1230
|
if (options.stop_watching)
|
|
1215
|
-
bus(prefix + '/*').
|
|
1231
|
+
bus(prefix + '/*').forgetter = function (key, json) {
|
|
1216
1232
|
console.assert(watching[key],
|
|
1217
1233
|
'Forgetting a watcher for ' + JSON.stringify(key)
|
|
1218
1234
|
+ ' that is not enabled')
|
|
@@ -1234,6 +1250,10 @@
|
|
|
1234
1250
|
})
|
|
1235
1251
|
}
|
|
1236
1252
|
|
|
1253
|
+
function aget (key) {
|
|
1254
|
+
return new Promise((resolve, reject) =>
|
|
1255
|
+
bus.get_once(key, (o) => resolve(o)))
|
|
1256
|
+
}
|
|
1237
1257
|
|
|
1238
1258
|
// ******************
|
|
1239
1259
|
// Proxy
|
|
@@ -1417,7 +1437,7 @@
|
|
|
1417
1437
|
return bus.translate_links(bus.clone(keyed), rem_prefix)
|
|
1418
1438
|
}
|
|
1419
1439
|
|
|
1420
|
-
bus(prefix).
|
|
1440
|
+
bus(prefix).setter = function (obj, t) {
|
|
1421
1441
|
bus.set.fire(obj)
|
|
1422
1442
|
var x = {set: obj}
|
|
1423
1443
|
if (t.version) x.version = t.version
|
|
@@ -1426,11 +1446,11 @@
|
|
|
1426
1446
|
if (t.patch) x.set = rem_prefix(x.set.key)
|
|
1427
1447
|
send(x)
|
|
1428
1448
|
}
|
|
1429
|
-
bus(prefix).
|
|
1449
|
+
bus(prefix).getter = function (key) { send({get: key}),
|
|
1430
1450
|
client_getted_keys.add(key) }
|
|
1431
|
-
bus(prefix).
|
|
1451
|
+
bus(prefix).forgetter = function (key) { send({forget: key}),
|
|
1432
1452
|
client_getted_keys.delete(key) }
|
|
1433
|
-
bus(prefix).
|
|
1453
|
+
bus(prefix).deleter = function (key) { send({'delete': key}) }
|
|
1434
1454
|
|
|
1435
1455
|
function connect () {
|
|
1436
1456
|
nlog('[ ] trying to open ' + url)
|
|
@@ -1933,7 +1953,7 @@
|
|
|
1933
1953
|
|
|
1934
1954
|
// This prune() function is a temporary workaround for dealing with nested
|
|
1935
1955
|
// objects in set() handlers, until we change statebus' behavior. Right
|
|
1936
|
-
// now, it calls .
|
|
1956
|
+
// now, it calls .setter only on the top-level state. But if that state
|
|
1937
1957
|
// validates, it calls fire() on *every* level of state. This means that
|
|
1938
1958
|
// state changes can sneak inside. Prune() will take out any changes from
|
|
1939
1959
|
// the nested levels of state in a new object -- replacing them with the
|
|
@@ -2115,7 +2135,7 @@
|
|
|
2115
2135
|
var api = ['cache backup_cache get set forget del fire dirty get_once',
|
|
2116
2136
|
'subspace bindings run_handler bind unbind reactive uncallback',
|
|
2117
2137
|
'versions new_version',
|
|
2118
|
-
'link',
|
|
2138
|
+
'link aget',
|
|
2119
2139
|
'funk_key funk_name funks key_id key_name id',
|
|
2120
2140
|
'pending_gets gets_in gets_out loading_keys loading once',
|
|
2121
2141
|
'global_funk busses rerunnable_funks',
|
|
@@ -2146,13 +2166,13 @@
|
|
|
2146
2166
|
bus.libs = {}
|
|
2147
2167
|
|
|
2148
2168
|
if (nodejs)
|
|
2149
|
-
require('./
|
|
2169
|
+
require('./server-library').import_server(bus, make_bus, options)
|
|
2150
2170
|
|
|
2151
2171
|
bus.render_when_loading = true
|
|
2152
2172
|
return bus
|
|
2153
2173
|
}
|
|
2154
2174
|
|
|
2155
|
-
if (nodejs) require('./
|
|
2175
|
+
if (nodejs) require('./server-library').import_module(make_bus)
|
|
2156
2176
|
|
|
2157
2177
|
return make_bus
|
|
2158
2178
|
}))
|