statebus 7.0.3 → 7.0.6
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} +310 -281
- package/extras/coffee.js +12 -0
- package/extras/sockjs.js +27 -0
- package/extras/tests.js +110 -106
- package/package.json +6 -4
- package/{servers.js → server-library.js} +338 -247
- package/statebus.js +140 -77
package/statebus.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
&& !(typeof key === 'object' && typeof key.key === 'string'))
|
|
15
15
|
throw ('Error: get(key) called with key = '
|
|
16
16
|
+ JSON.stringify(key))
|
|
17
|
-
key = key.key || key
|
|
18
|
-
|
|
17
|
+
key = key.key || key // You can pass in an object instead of key
|
|
18
|
+
// We should probably disable this in future
|
|
19
19
|
bogus_check(key)
|
|
20
20
|
|
|
21
21
|
var called_from_reactive_funk = !callback
|
|
@@ -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,10 +409,11 @@
|
|
|
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]
|
|
416
|
+
// delete backup_cache[key]
|
|
416
417
|
delete gets_out[key]
|
|
417
418
|
delete to_be_forgotten[key]
|
|
418
419
|
}, 200)
|
|
@@ -428,11 +429,13 @@
|
|
|
428
429
|
}
|
|
429
430
|
|
|
430
431
|
statelog(key, yellow, 'v', 'Deleting ' + key)
|
|
431
|
-
// Call the
|
|
432
|
-
var handlers_called = bus.route(key, '
|
|
433
|
-
if (handlers_called === 0)
|
|
432
|
+
// Call the deleter handlers
|
|
433
|
+
var handlers_called = bus.route(key, 'deleter', key)
|
|
434
|
+
if (handlers_called === 0) {
|
|
434
435
|
// And go ahead and delete if there aren't any!
|
|
435
436
|
delete cache[key]
|
|
437
|
+
delete backup_cache[key]
|
|
438
|
+
}
|
|
436
439
|
|
|
437
440
|
// Call the on_delete handlers
|
|
438
441
|
bus.route(key, 'on_delete', cache[key] || {key: key}, t)
|
|
@@ -444,11 +447,11 @@
|
|
|
444
447
|
// - Add transactions, so you can check permissions, abort a delete,
|
|
445
448
|
// etc.
|
|
446
449
|
// - NOTE: I did a crappy implementation of abort just now above!
|
|
447
|
-
// But it doesn't work if called after the
|
|
450
|
+
// But it doesn't work if called after the deleter handler returns.
|
|
448
451
|
// - Generalize the code across set and del with a "mutate"
|
|
449
452
|
// operation
|
|
450
453
|
//
|
|
451
|
-
// - Right now we fire the
|
|
454
|
+
// - Right now we fire the deleter handlers right here.
|
|
452
455
|
//
|
|
453
456
|
// - Do we want to batch them up and fire them later?
|
|
454
457
|
// e.g. we could make a mark_deleted(key) like mark_changed(key)
|
|
@@ -467,7 +470,7 @@
|
|
|
467
470
|
|
|
468
471
|
var version = (t && t.version) || 'dirty-' + new_version()
|
|
469
472
|
|
|
470
|
-
// Find any .
|
|
473
|
+
// Find any .getter, and mark as dirty so that it re-runs
|
|
471
474
|
var found = false
|
|
472
475
|
if (gets_out.hasOwnProperty(key))
|
|
473
476
|
for (var i=0; i<gets_out[key].length; i++) {
|
|
@@ -503,7 +506,6 @@
|
|
|
503
506
|
var funk = funks[k],
|
|
504
507
|
version = dirty_funks[k]
|
|
505
508
|
|
|
506
|
-
// console.log(funks[dirty_funks[i]].proxies_for)
|
|
507
509
|
var p = funk.proxies_for
|
|
508
510
|
if (p && p.priority) {
|
|
509
511
|
log('Clean-early:', funk_name(funk))
|
|
@@ -525,7 +527,7 @@
|
|
|
525
527
|
funk.react()
|
|
526
528
|
}
|
|
527
529
|
}
|
|
528
|
-
// log('We just cleaned up', dirty_funks.length, 'funks!')
|
|
530
|
+
// console.log('We just cleaned up', dirty_funks.length, 'funks!')
|
|
529
531
|
}
|
|
530
532
|
|
|
531
533
|
// Let's change this function to go through each key and grab the latest
|
|
@@ -537,7 +539,7 @@
|
|
|
537
539
|
var result = []
|
|
538
540
|
var keys = changed_keys.values()
|
|
539
541
|
|
|
540
|
-
//log(bus+'
|
|
542
|
+
// console.log(bus+' Finding rerunnable funcs for', keys, 'keys, and', Object.keys(dirty_getters).length, 'dirty_getters')
|
|
541
543
|
for (var i=0; i<keys.length; i++) { // Collect all keys
|
|
542
544
|
// if (to_be_forgotten[keys[i]])
|
|
543
545
|
// // Ignore changes to keys that have been forgotten, but not
|
|
@@ -549,7 +551,7 @@
|
|
|
549
551
|
if (f.react) {
|
|
550
552
|
// Skip if it's already up to date
|
|
551
553
|
var v = f.getted_keys[JSON.stringify([this.id, keys[i]])]
|
|
552
|
-
//log('re-run:', keys[i], f.statebus_id, f.getted_keys)
|
|
554
|
+
// console.log('re-run:', keys[i], f.statebus_id, f.getted_keys)
|
|
553
555
|
if (v && v.indexOf(versions[keys[i]]) !== -1) {
|
|
554
556
|
log('skipping', funk_name(f), 'already at version', versions[keys[i]], 'proof:', v)
|
|
555
557
|
continue
|
|
@@ -580,7 +582,7 @@
|
|
|
580
582
|
changed_keys.clear()
|
|
581
583
|
dirty_getters = {}
|
|
582
584
|
|
|
583
|
-
//log('found', result.length, 'funks to re run')
|
|
585
|
+
// console.log('found', result.length, 'funks to re run')
|
|
584
586
|
|
|
585
587
|
return result
|
|
586
588
|
}
|
|
@@ -588,13 +590,21 @@
|
|
|
588
590
|
// ****************
|
|
589
591
|
// Connections
|
|
590
592
|
function subspace (key, params) {
|
|
591
|
-
var methods = {
|
|
592
|
-
on_delete:null,
|
|
593
|
+
var methods = {getter:null, setter:null, on_set:null, on_set_sync:null,
|
|
594
|
+
on_delete:null, deleter:null, forgetter:null}
|
|
593
595
|
|
|
594
596
|
if (params) {
|
|
595
597
|
for (var method in params) {
|
|
596
|
-
console.assert(method in methods)
|
|
597
598
|
var func = params[method]
|
|
599
|
+
var param_names = {get:'getter', set:'setter',
|
|
600
|
+
delete: 'deleter', forget: 'forgetter',
|
|
601
|
+
on_set:'on_set', on_set_sync:'on_set_sync'}
|
|
602
|
+
|
|
603
|
+
// Map it from the API's name to our internal name
|
|
604
|
+
console.assert(param_names[method],
|
|
605
|
+
'Method "' + method + '" is invalid')
|
|
606
|
+
method = param_names[method]
|
|
607
|
+
|
|
598
608
|
autodetect_args(func)
|
|
599
609
|
func.defined = func.defined || []
|
|
600
610
|
func.defined.push({bus, method, key, as: 'handler'})
|
|
@@ -756,8 +766,8 @@
|
|
|
756
766
|
|
|
757
767
|
if (false && !funck.global_funk) {
|
|
758
768
|
// \u26A1
|
|
759
|
-
var event = {'
|
|
760
|
-
'
|
|
769
|
+
var event = {'setter':'set','on_set':'set.fire','getter':'get',
|
|
770
|
+
'deleter':'delete','forgetter':'forget'}[method],
|
|
761
771
|
triggering = funk ? 're-running' : 'initiating'
|
|
762
772
|
console.log(' > a', bus+'.'+event + "('" + (arg.key||arg) + "') is " + triggering
|
|
763
773
|
+'\n ' + funk_name(funck))
|
|
@@ -802,7 +812,8 @@
|
|
|
802
812
|
function key_arg () { return ((typeof arg.key) == 'string') ? arg.key : arg }
|
|
803
813
|
function rest_arg () { return (key_arg()).substr(binding.length-1) }
|
|
804
814
|
function val_arg () {
|
|
805
|
-
console.assert(method === '
|
|
815
|
+
console.assert(method === 'setter' || method === 'on_set' || method === 'on_set_sync',
|
|
816
|
+
'Bad method for val_arg()')
|
|
806
817
|
// Is there a time I am supposed to return bus.cache[arg]? It used to say:
|
|
807
818
|
// arg.key ? arg : bus.cache[arg]
|
|
808
819
|
|
|
@@ -821,9 +832,9 @@
|
|
|
821
832
|
t = clone(t || {})
|
|
822
833
|
|
|
823
834
|
// Add .abort() method
|
|
824
|
-
if (method === '
|
|
835
|
+
if (method === 'setter' || method === 'deleter')
|
|
825
836
|
t.abort = function () {
|
|
826
|
-
var key = method === '
|
|
837
|
+
var key = method === 'setter' ? arg.key : arg
|
|
827
838
|
if (f.loading()) return
|
|
828
839
|
bus.cache[key] = bus.cache[key] || {key: key}
|
|
829
840
|
bus.backup_cache[key] = bus.backup_cache[key] || {key: key}
|
|
@@ -831,34 +842,36 @@
|
|
|
831
842
|
}
|
|
832
843
|
|
|
833
844
|
// Add .done() method
|
|
834
|
-
if (method !== '
|
|
845
|
+
if (method !== 'forgetter')
|
|
835
846
|
t.done = function (o) {
|
|
836
|
-
var key = method === '
|
|
847
|
+
var key = method === 'setter' ? arg.key : arg
|
|
837
848
|
if (func.use_linked_json)
|
|
838
849
|
o = {key, val: o}
|
|
839
850
|
bus.log('We are DONE()ing', method, key, o||arg)
|
|
840
851
|
|
|
841
852
|
// We use a simple (and crappy?) heuristic to know if the
|
|
842
|
-
//
|
|
853
|
+
// setter handler has changed the state: whether the
|
|
843
854
|
// programmer passed (o) to the t.done(o) handler. If
|
|
844
855
|
// not, we assume it hasn't changed. If so, we assume it
|
|
845
856
|
// *has* changed, and thus we change the version of the
|
|
846
857
|
// state. I imagine it would be more accurate to diff
|
|
847
|
-
// from before the
|
|
858
|
+
// from before the setter handler began with when
|
|
848
859
|
// t.done(o) ran.
|
|
849
860
|
//
|
|
850
861
|
// Note: We will likely solve this in the future by
|
|
851
|
-
// preventing .
|
|
862
|
+
// preventing .setter() from changing the incoming state,
|
|
852
863
|
// except through an explicit .revise() function.
|
|
853
864
|
if (o) t.version = new_version()
|
|
854
865
|
|
|
855
|
-
if (method === '
|
|
866
|
+
if (method === 'deleter') {
|
|
856
867
|
delete bus.cache[key]
|
|
857
|
-
|
|
868
|
+
delete bus.backup_cache[key]
|
|
869
|
+
}
|
|
870
|
+
else if (method === 'setter') {
|
|
858
871
|
bus.set.fire(o || arg, t)
|
|
859
872
|
bus.route(key, 'on_set_sync', o || arg, t)
|
|
860
873
|
} else {
|
|
861
|
-
// Now method === '
|
|
874
|
+
// Now method === 'getter'
|
|
862
875
|
o.key = key
|
|
863
876
|
bus.set.fire(o, t)
|
|
864
877
|
// And now reset the version cause it could get called again
|
|
@@ -869,14 +882,20 @@
|
|
|
869
882
|
// Alias .return() to .done(), in case that feels better to you
|
|
870
883
|
t.return = t.done
|
|
871
884
|
|
|
885
|
+
// Prepush Scratch:
|
|
886
|
+
// var prepushed = {}
|
|
887
|
+
// t.prepush = function (key) {
|
|
888
|
+
// prepushed[key] = bus.get(key)
|
|
889
|
+
// }
|
|
890
|
+
|
|
872
891
|
// Alias t.reget() to bus.dirty()
|
|
873
|
-
if (method === '
|
|
892
|
+
if (method === 'setter')
|
|
874
893
|
t.reget = function () { bus.dirty(arg.key) }
|
|
875
894
|
|
|
876
895
|
// Now to call the handler, let's line up the function's special
|
|
877
896
|
// named arguemnts like key, o, t, rest, vars, etc.
|
|
878
897
|
var args = []
|
|
879
|
-
args[0] = (method in {
|
|
898
|
+
args[0] = (method in {setter:1, on_set:1, on_set_sync:1}) ? val_arg() : arg
|
|
880
899
|
args[1] = t
|
|
881
900
|
for (var k in (func.args||{})) {
|
|
882
901
|
switch (k) {
|
|
@@ -907,28 +926,29 @@
|
|
|
907
926
|
// arr[func.args[k]] = <compute_blah(k)>
|
|
908
927
|
|
|
909
928
|
// Trigger done() or abort() by return value
|
|
910
|
-
console.assert(!(result === '
|
|
929
|
+
console.assert(!(result === 'getter' &&
|
|
911
930
|
(result === 'done' || result === 'abort')),
|
|
912
|
-
'Returning "done" or "abort" is not allowed from
|
|
931
|
+
'Returning "done" or "abort" is not allowed from getter handlers')
|
|
932
|
+
|
|
913
933
|
if (result === 'done') t.done()
|
|
914
934
|
if (result === 'abort') t.abort()
|
|
915
935
|
|
|
916
936
|
// For get
|
|
917
937
|
if (func.use_linked_json) {
|
|
918
|
-
if (method === '
|
|
938
|
+
if (method === 'getter' && result !== undefined && !f.loading()) {
|
|
919
939
|
var obj = {key: arg, val: result}
|
|
920
940
|
var new_t = clone(t || {})
|
|
921
|
-
new_t.
|
|
941
|
+
new_t.getter = true
|
|
922
942
|
set.fire(obj, new_t)
|
|
923
943
|
return result
|
|
924
944
|
}
|
|
925
945
|
} else {
|
|
926
|
-
if (method === '
|
|
946
|
+
if (method === 'getter' && result instanceof Object
|
|
927
947
|
&& !f.loading() // Experimental.
|
|
928
948
|
) {
|
|
929
949
|
result.key = arg
|
|
930
950
|
var new_t = clone(t || {})
|
|
931
|
-
new_t.
|
|
951
|
+
new_t.getter = true
|
|
932
952
|
set.fire(result, new_t)
|
|
933
953
|
return result
|
|
934
954
|
}
|
|
@@ -937,29 +957,29 @@
|
|
|
937
957
|
// Set, forget and delete handlers stop re-running once they've
|
|
938
958
|
// completed without anything loading.
|
|
939
959
|
// ... with f.forget()
|
|
940
|
-
if (method !== '
|
|
960
|
+
if (method !== 'getter' && !f.loading())
|
|
941
961
|
f.forget()
|
|
942
962
|
})
|
|
943
963
|
f.proxies_for = func
|
|
944
964
|
f.arg = arg
|
|
945
965
|
f.transaction = t || {}
|
|
946
966
|
|
|
947
|
-
//
|
|
948
|
-
if (method === '
|
|
967
|
+
// getter handlers stop re-running when the key is forgotten
|
|
968
|
+
if (method === 'getter') {
|
|
949
969
|
var key = arg
|
|
950
970
|
function handler_done () {
|
|
951
971
|
f.forget()
|
|
952
|
-
unbind(key, '
|
|
972
|
+
unbind(key, 'forgetter', handler_done)
|
|
953
973
|
}
|
|
954
|
-
bind(key, '
|
|
974
|
+
bind(key, 'forgetter', handler_done)
|
|
955
975
|
|
|
956
976
|
// // Check if it's doubled-up
|
|
957
977
|
// if (gets_out[key])
|
|
958
|
-
// console.error('Two .
|
|
978
|
+
// console.error('Two .getter functions are running on the same key',
|
|
959
979
|
// key+'!', funk_name(funck), funk_name(gets_out[key]))
|
|
960
980
|
|
|
961
981
|
gets_out[key] = gets_out[key] || []
|
|
962
|
-
gets_out[key].push(f) // Record active
|
|
982
|
+
gets_out[key].push(f) // Record active getter handler
|
|
963
983
|
pending_gets[key] = f // Record that the get is pending
|
|
964
984
|
}
|
|
965
985
|
|
|
@@ -979,9 +999,9 @@
|
|
|
979
999
|
for (var i=0; i<handlers.length; i++)
|
|
980
1000
|
bus.run_handler(handlers[i].func, method, arg, {t: t, binding: handlers[i].key})
|
|
981
1001
|
|
|
982
|
-
// if (method === '
|
|
1002
|
+
// if (method === 'getter')
|
|
983
1003
|
// console.assert(handlers.length<2,
|
|
984
|
-
// 'Two
|
|
1004
|
+
// 'Two getter functions are registered for the same key '+key,
|
|
985
1005
|
// handlers)
|
|
986
1006
|
return handlers.length
|
|
987
1007
|
}
|
|
@@ -1187,7 +1207,7 @@
|
|
|
1187
1207
|
if (!name) throw 'Uncallback function needs a name'
|
|
1188
1208
|
var watching = {}
|
|
1189
1209
|
var prefix = 'uncallback/' + name
|
|
1190
|
-
bus(prefix + '/*').
|
|
1210
|
+
bus(prefix + '/*').getter = function (key, json) {
|
|
1191
1211
|
var args = json
|
|
1192
1212
|
function cb (err, result) {
|
|
1193
1213
|
if (err) {
|
|
@@ -1212,7 +1232,7 @@
|
|
|
1212
1232
|
}
|
|
1213
1233
|
}
|
|
1214
1234
|
if (options.stop_watching)
|
|
1215
|
-
bus(prefix + '/*').
|
|
1235
|
+
bus(prefix + '/*').forgetter = function (key, json) {
|
|
1216
1236
|
console.assert(watching[key],
|
|
1217
1237
|
'Forgetting a watcher for ' + JSON.stringify(key)
|
|
1218
1238
|
+ ' that is not enabled')
|
|
@@ -1234,6 +1254,10 @@
|
|
|
1234
1254
|
})
|
|
1235
1255
|
}
|
|
1236
1256
|
|
|
1257
|
+
function aget (key) {
|
|
1258
|
+
return new Promise((resolve, reject) =>
|
|
1259
|
+
bus.get_once(key, (o) => resolve(o)))
|
|
1260
|
+
}
|
|
1237
1261
|
|
|
1238
1262
|
// ******************
|
|
1239
1263
|
// Proxy
|
|
@@ -1258,8 +1282,8 @@
|
|
|
1258
1282
|
return o
|
|
1259
1283
|
|
|
1260
1284
|
// We recursively descend through {key: ...} links
|
|
1261
|
-
if (typeof o === 'object' && '
|
|
1262
|
-
var new_base = bus.get(o.
|
|
1285
|
+
if (typeof o === 'object' && 'link' in o) {
|
|
1286
|
+
var new_base = bus.get(o.link)
|
|
1263
1287
|
return item_proxy(new_base, new_base.val)
|
|
1264
1288
|
}
|
|
1265
1289
|
|
|
@@ -1409,11 +1433,15 @@
|
|
|
1409
1433
|
function rem_prefix (key) {
|
|
1410
1434
|
return has_prefix.test(key) ? key.substr(preprefix.length) : key }
|
|
1411
1435
|
function add_prefixes (obj) {
|
|
1412
|
-
|
|
1436
|
+
var keyed = bus.translate_keys(bus.clone(obj), add_prefix)
|
|
1437
|
+
return bus.translate_links(bus.clone(keyed), add_prefix)
|
|
1438
|
+
}
|
|
1413
1439
|
function rem_prefixes (obj) {
|
|
1414
|
-
|
|
1440
|
+
var keyed = bus.translate_keys(bus.clone(obj), rem_prefix)
|
|
1441
|
+
return bus.translate_links(bus.clone(keyed), rem_prefix)
|
|
1442
|
+
}
|
|
1415
1443
|
|
|
1416
|
-
bus(prefix).
|
|
1444
|
+
bus(prefix).setter = function (obj, t) {
|
|
1417
1445
|
bus.set.fire(obj)
|
|
1418
1446
|
var x = {set: obj}
|
|
1419
1447
|
if (t.version) x.version = t.version
|
|
@@ -1422,11 +1450,14 @@
|
|
|
1422
1450
|
if (t.patch) x.set = rem_prefix(x.set.key)
|
|
1423
1451
|
send(x)
|
|
1424
1452
|
}
|
|
1425
|
-
bus(prefix).
|
|
1453
|
+
bus(prefix).getter = function (key) { send({get: key}),
|
|
1426
1454
|
client_getted_keys.add(key) }
|
|
1427
|
-
bus(prefix).
|
|
1455
|
+
bus(prefix).forgetter = function (key) { send({forget: key}),
|
|
1428
1456
|
client_getted_keys.delete(key) }
|
|
1429
|
-
bus(prefix).
|
|
1457
|
+
bus(prefix).deleter = function (key, t) {
|
|
1458
|
+
t.done()
|
|
1459
|
+
send({'delete': key})
|
|
1460
|
+
}
|
|
1430
1461
|
|
|
1431
1462
|
function connect () {
|
|
1432
1463
|
nlog('[ ] trying to open ' + url)
|
|
@@ -1446,9 +1477,9 @@
|
|
|
1446
1477
|
var i = []
|
|
1447
1478
|
function intro (o) {i.push(JSON.stringify({set: o}))}
|
|
1448
1479
|
if (creds.clientid)
|
|
1449
|
-
intro({key: 'current_user', client: creds.clientid})
|
|
1480
|
+
intro({key: 'current_user', val: {client: creds.clientid}})
|
|
1450
1481
|
if (creds.name && creds.pass)
|
|
1451
|
-
intro({key: 'current_user', login_as: {name: creds.name, pass: creds.pass}})
|
|
1482
|
+
intro({key: 'current_user', val: {login_as: {name: creds.name, pass: creds.pass}}})
|
|
1452
1483
|
// Todo: make this kinda thing work:
|
|
1453
1484
|
if (creds.private_key && creds.public_key) {
|
|
1454
1485
|
// Send public_key... start waiting for a
|
|
@@ -1540,6 +1571,14 @@
|
|
|
1540
1571
|
return {send: send, sock: sock, close: function () {done = true; sock.close()}}
|
|
1541
1572
|
}
|
|
1542
1573
|
|
|
1574
|
+
bus.client_creds = function client_creds (server_url) {
|
|
1575
|
+
// This default implementation just creates a different random id each time
|
|
1576
|
+
// we connect. Override this if you want a client ID that persists.
|
|
1577
|
+
return {clientid: (Math.random().toString(36).substring(2)
|
|
1578
|
+
+ Math.random().toString(36).substring(2)
|
|
1579
|
+
+ Math.random().toString(36).substring(2))}
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1543
1582
|
function net_automount () {
|
|
1544
1583
|
var bus = this
|
|
1545
1584
|
var old_route = bus.route
|
|
@@ -1586,6 +1625,30 @@
|
|
|
1586
1625
|
return k.replace(/(_$)/, '')
|
|
1587
1626
|
}
|
|
1588
1627
|
|
|
1628
|
+
// ************************************************
|
|
1629
|
+
// Translating the URLs under links of state
|
|
1630
|
+
function translate_links (obj, f) {
|
|
1631
|
+
// Recurse through each element in arrays
|
|
1632
|
+
if (Array.isArray(obj))
|
|
1633
|
+
for (var i=0; i < obj.length; i++)
|
|
1634
|
+
translate_links(obj[i], f)
|
|
1635
|
+
|
|
1636
|
+
// Recurse through each property on objects
|
|
1637
|
+
else if (typeof obj === 'object')
|
|
1638
|
+
for (var k in obj) {
|
|
1639
|
+
if (k === 'link')
|
|
1640
|
+
if (typeof obj[k] == 'string')
|
|
1641
|
+
obj[k] = f(obj[k])
|
|
1642
|
+
else if (Array.isArray(obj[k]))
|
|
1643
|
+
for (var i=0; i < obj[k].length; i++) {
|
|
1644
|
+
if (typeof obj[k][i] === 'string')
|
|
1645
|
+
obj[k][i] = f(obj[k][i])
|
|
1646
|
+
}
|
|
1647
|
+
translate_links(obj[k], f)
|
|
1648
|
+
}
|
|
1649
|
+
return obj
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1589
1652
|
|
|
1590
1653
|
// ************************************************
|
|
1591
1654
|
// Translating fields of objects
|
|
@@ -1863,13 +1926,13 @@
|
|
|
1863
1926
|
if (a_array !== b_array) return ' = ' + JSON.stringify(b)
|
|
1864
1927
|
if (a_array) {
|
|
1865
1928
|
if (a.length === b.length-1
|
|
1866
|
-
&&
|
|
1867
|
-
return '.push(' +JSON.stringify(b[b.length]) + ')'
|
|
1929
|
+
&& deep_equals(a[a.length-1], b[b.length-2])) {
|
|
1930
|
+
return '.push(' +JSON.stringify(b[b.length-1]) + ')'
|
|
1868
1931
|
}
|
|
1869
1932
|
for (var i=0; i < a.length; i++) {
|
|
1870
1933
|
var tmp = sorta_diff (a[i], b[i])
|
|
1871
1934
|
if (tmp)
|
|
1872
|
-
return '['+i+']
|
|
1935
|
+
return '['+i+']'+tmp
|
|
1873
1936
|
}
|
|
1874
1937
|
return null
|
|
1875
1938
|
}
|
|
@@ -1897,7 +1960,7 @@
|
|
|
1897
1960
|
|
|
1898
1961
|
// This prune() function is a temporary workaround for dealing with nested
|
|
1899
1962
|
// objects in set() handlers, until we change statebus' behavior. Right
|
|
1900
|
-
// now, it calls .
|
|
1963
|
+
// now, it calls .setter only on the top-level state. But if that state
|
|
1901
1964
|
// validates, it calls fire() on *every* level of state. This means that
|
|
1902
1965
|
// state changes can sneak inside. Prune() will take out any changes from
|
|
1903
1966
|
// the nested levels of state in a new object -- replacing them with the
|
|
@@ -2070,7 +2133,7 @@
|
|
|
2070
2133
|
if (!(key in bogus_keys))
|
|
2071
2134
|
return
|
|
2072
2135
|
|
|
2073
|
-
var msg = "Sorry, statebus.js currently prohibits use of the key \""+key+"\", and in fact all of these keys: " + Object.keys(bogus_keys).join(', ') + ". This is because Javascript is kinda lame, and even empty objects like \"{}\" have the \""+key+"\" field defined on them. Try typing this in your Javascript console: \"({}).constructor\" -- it returns a function instead of undefined!
|
|
2136
|
+
var msg = "Sorry, statebus.js currently prohibits use of the key \""+key+"\", and in fact all of these keys: " + Object.keys(bogus_keys).join(', ') + ". This is because Javascript is kinda lame, and even empty objects like \"{}\" have the \""+key+"\" field defined on them. Try typing this in your Javascript console: \"({}).constructor\" -- it returns a function instead of undefined! Mike needs to work around it by replacing every \"obj[key]\" with \"obj.hasOwnProperty(key) && obj[key]\" in the statebus code, or switching to a Map() object. Please contact him and let him know where this is impacting you, so he can bump the priority on it."
|
|
2074
2137
|
console.error(msg)
|
|
2075
2138
|
throw 'Invalid key'
|
|
2076
2139
|
}
|
|
@@ -2079,11 +2142,11 @@
|
|
|
2079
2142
|
var api = ['cache backup_cache get set forget del fire dirty get_once',
|
|
2080
2143
|
'subspace bindings run_handler bind unbind reactive uncallback',
|
|
2081
2144
|
'versions new_version',
|
|
2082
|
-
'link',
|
|
2145
|
+
'link aget',
|
|
2083
2146
|
'funk_key funk_name funks key_id key_name id',
|
|
2084
2147
|
'pending_gets gets_in gets_out loading_keys loading once',
|
|
2085
2148
|
'global_funk busses rerunnable_funks',
|
|
2086
|
-
'escape_keys unescape_keys translate_keys apply_patch',
|
|
2149
|
+
'escape_keys unescape_keys translate_keys translate_links apply_patch',
|
|
2087
2150
|
'keyed_2_proxied proxied_2_keyed translate_fields',
|
|
2088
2151
|
'ws_mount net_automount message_method',
|
|
2089
2152
|
'parse Set One_To_Many clone extend deep_map deep_equals prune validate sorta_diff log deps symbols'
|
|
@@ -2110,13 +2173,13 @@
|
|
|
2110
2173
|
bus.libs = {}
|
|
2111
2174
|
|
|
2112
2175
|
if (nodejs)
|
|
2113
|
-
require('./
|
|
2176
|
+
require('./server-library').import_server(bus, make_bus, options)
|
|
2114
2177
|
|
|
2115
2178
|
bus.render_when_loading = true
|
|
2116
2179
|
return bus
|
|
2117
2180
|
}
|
|
2118
2181
|
|
|
2119
|
-
if (nodejs) require('./
|
|
2182
|
+
if (nodejs) require('./server-library').import_module(make_bus)
|
|
2120
2183
|
|
|
2121
2184
|
return make_bus
|
|
2122
2185
|
}))
|