statebus 7.0.1 → 7.0.4

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 CHANGED
@@ -43,19 +43,21 @@
43
43
  // return new SockJS(url + '/' + websocket_prefix)
44
44
  }
45
45
  function client_creds (server_url) {
46
+ // This function is only used for websocket connections.
47
+ // http connections set the cookie on the server.
46
48
  var me = bus.get('ls/me')
47
49
  bus.log('connect: me is', me)
48
50
  if (!me.client) {
49
51
  // Create a client id if we have none yet.
50
52
  // Either from a cookie set by server, or a new one from scratch.
51
- var c = get_cookie('client')
53
+ var c = get_cookie('peer')
52
54
  me.client = c || (Math.random().toString(36).substring(2)
53
55
  + Math.random().toString(36).substring(2)
54
56
  + Math.random().toString(36).substring(2))
55
57
  bus.set(me)
56
58
  }
57
59
 
58
- set_cookie('client', me.client)
60
+ set_cookie('peer', me.client)
59
61
  return {clientid: me.client}
60
62
  }
61
63
 
@@ -66,14 +68,18 @@
66
68
  var subscriptions = {}
67
69
  var put_counter = 0
68
70
 
69
- function add_prefix (key) {
70
- return is_absolute.test(key) ? key : preprefix + key }
71
- function rem_prefix (key) {
72
- return has_prefix.test(key) ? key.substr(preprefix.length) : key }
71
+ function add_prefix (url) {
72
+ return is_absolute.test(url) ? url : preprefix + url }
73
+ function rem_prefix (url) {
74
+ return has_prefix.test(url) ? url.substr(preprefix.length) : url }
73
75
  function add_prefixes (obj) {
74
- return bus.translate_keys(bus.clone(obj), add_prefix) }
76
+ var keyed = bus.translate_keys(bus.clone(obj), add_prefix)
77
+ return bus.translate_links(bus.clone(keyed), add_prefix)
78
+ }
75
79
  function rem_prefixes (obj) {
76
- return bus.translate_keys(bus.clone(obj), rem_prefix) }
80
+ var keyed = bus.translate_keys(bus.clone(obj), rem_prefix)
81
+ return bus.translate_links(bus.clone(keyed), rem_prefix)
82
+ }
77
83
 
78
84
  var puts = new Map()
79
85
  function enqueue_put (url, body) {
@@ -112,11 +118,12 @@
112
118
  setTimeout(function () {send_put(id)}, 1000)
113
119
  }
114
120
  function send_all_puts () {
115
- for (var id of puts.keys())
116
- if (puts.get(id).status === 'waiting') {
121
+ puts.forEach(function (value, id) {
122
+ if (value.status === 'waiting') {
117
123
  console.log('Sending waiting put', id)
118
124
  send_put(id)
119
125
  }
126
+ })
120
127
  }
121
128
 
122
129
  bus(prefix).to_set = function (obj, t) {
@@ -218,6 +225,25 @@
218
225
  }
219
226
  }
220
227
 
228
+ function http_automount () {
229
+ function get_domain (key) { // Returns e.g. "state://foo.com"
230
+ var m = key.match(/^https?\:\/\/(([^:\/?#]*)(?:\:([0-9]+))?)/)
231
+ return m && m[0]
232
+ }
233
+
234
+ var old_route = bus.route
235
+ var connections = {}
236
+ bus.route = function (key, method, arg, t) {
237
+ var d = get_domain(key)
238
+ if (d && !connections[d]) {
239
+ http_mount(d + '/*', d + '/')
240
+ connections[d] = true
241
+ }
242
+
243
+ return old_route(key, method, arg, t)
244
+ }
245
+ }
246
+
221
247
 
222
248
  // ****************
223
249
  // Manipulate Localstorage
@@ -476,30 +502,8 @@
476
502
  }
477
503
  }
478
504
 
479
- function load_scripts() {
480
- // console.info('Loading scripts! if', !!!window.statebus)
481
- if (!window.statebus) {
482
- var statebus_dir = clientjs_option('src')
483
- if (statebus_dir) statebus_dir = statebus_dir.match(/(.*)[\/\\]/)
484
- if (statebus_dir) statebus_dir = statebus_dir[1] + '/'
485
- else statebus_dir = ''
486
-
487
- // var js_urls = {
488
- // react: statebus_dir + 'extras/react.js',
489
- // sockjs: statebus_dir + 'extras/sockjs.js',
490
- // coffee: statebus_dir + 'extras/coffee.js',
491
- // statebus: statebus_dir + 'statebus.js'
492
- // }
493
- // if (statebus_dir == 'https://stateb.us/')
494
- // js_urls.statebus = statebus_dir + 'statebus4.js'
495
-
496
- // for (var name in js_urls)
497
- // document.write('<script src="' + js_urls[name] + '" charset="utf-8"></script>')
498
-
499
- document.addEventListener('DOMContentLoaded', scripts_ready, false)
500
- }
501
- else
502
- scripts_ready()
505
+ function load_scripts () {
506
+ scripts_ready()
503
507
  }
504
508
 
505
509
  function clientjs_option (option_name) {
@@ -519,11 +523,8 @@
519
523
  window.bus = window.statebus()
520
524
  bus.label = 'bus'
521
525
 
522
- statebus.create_react_class = create_react_class
523
- statebus.createReactClass = create_react_class
524
-
525
526
  // improve_react()
526
- statebus.ignore_flashbacks = false
527
+ // statebus.ignore_flashbacks = false
527
528
  bus.libs = {}
528
529
  bus.libs.http_out = http_mount
529
530
  bus.libs.react_class = create_react_class
@@ -539,26 +540,14 @@
539
540
  // }
540
541
  // }
541
542
 
542
- bus.net_automount()
543
-
544
- // This /new/* code is deprecated
545
- if (!clientjs_option('braid_mode')) {
546
- bus('/new/*').to_set = function (o) {
547
- if (o.key.split('/').length > 3) return
548
-
549
- var old_key = o.key
550
- o.key = old_key + '/' + Math.random().toString(36).substring(2,12)
551
- statebus.cache[o.key] = o
552
- delete statebus.cache[old_key]
553
- bus.set(o)
554
- }
555
- }
543
+ // bus.net_automount()
544
+ http_automount()
556
545
 
557
546
  load_coffee()
558
547
 
559
548
  statebus.compile_coffee = compile_coffee
560
549
  statebus.load_client_code = load_client_code
561
- statebus.load_widgets = load_widgets
550
+ // statebus.load_widgets = load_widgets
562
551
 
563
552
  if (clientjs_option('globals')) {
564
553
  // Setup globals
@@ -577,7 +566,7 @@
577
566
  statebus_ready[i]()
578
567
  }, false)
579
568
 
580
- document.addEventListener('DOMContentLoaded', load_widgets, false)
569
+ // document.addEventListener('DOMContentLoaded', load_widgets, false)
581
570
 
582
571
  // if (dom.Body || dom.body || dom.BODY)
583
572
  // react_render((window.Body || window.body || window.BODY)(), document.body)
@@ -753,7 +742,7 @@
753
742
  function make_component(name, func) {
754
743
  // Define the component
755
744
 
756
- window[name] = users_widgets[name] = statebus.create_react_class({
745
+ window[name] = users_widgets[name] = statebus.libs.react_class({
757
746
  displayName: name,
758
747
  render: function () {
759
748
  var args = []
@@ -803,103 +792,6 @@
803
792
  })
804
793
  }
805
794
 
806
- function make_syncarea () {
807
- // a textarea that syncs with other textareas via diffsync
808
- // options:
809
- // textarea_style : hashmap of styles to add to the textarea
810
- // cursor_style : hashmap of styles to add to each peer's cursor
811
- // autosize : true --> resizes the textarea vertically to fit the text inside it
812
- // ws_url : websocket url for the diffsync server,
813
- // e.g. 'wss://invisible.college:' + diffsync.port
814
- // channel : 'diffsync_channel' --> diffsync channel to connect to
815
- window['SYNCAREA'] = users_widgets['SYNCAREA'] = React.createClass({
816
- getInitialState : function () {
817
- return { cursor_positions : {} }
818
- },
819
- on_text_changed : function () {
820
- if (this.props.autosize) {
821
- var t = this.textarea_ref
822
- t.style.height = null
823
- while (t.rows > 1 && t.scrollHeight < t.offsetHeight) t.rows--
824
- while (t.scrollHeight > t.offsetHeight) t.rows++
825
- }
826
- },
827
- componentDidMount : function () {
828
- var self = this
829
- self.on_ranges = function (ranges) {
830
- self.ranges = ranges
831
- var cursor_positions = {}
832
- Object.keys(ranges).forEach(function (k) {
833
- var r = ranges[k]
834
- var xy = getCaretCoordinates(self.textarea_ref, r[0])
835
- var x = self.textarea_ref.offsetLeft - self.textarea_ref.scrollLeft + xy.left + 'px'
836
- var y = self.textarea_ref.offsetTop - self.textarea_ref.scrollTop + xy.top + 'px'
837
- cursor_positions[k] = [x, y]
838
- })
839
- self.setState({ cursor_positions : cursor_positions })
840
- }
841
-
842
- this.ds = diffsync.create_client({
843
- ws_url : this.props.ws_url,
844
- channel : this.props.channel,
845
- get_text : function () {
846
- return self.textarea_ref.value
847
- },
848
- get_range : function () {
849
- var t = self.textarea_ref
850
- return [t.selectionStart, t.selectionEnd]
851
- },
852
- on_text : function (s, range) {
853
- self.textarea_ref.value = s
854
- self.textarea_ref.setSelectionRange(range[0], range[1])
855
- self.on_text_changed()
856
- },
857
- on_ranges : this.on_ranges
858
- })
859
- },
860
- render : function () {
861
- var self = this
862
- var cursors = []
863
- Object.keys(this.state.cursor_positions).forEach(function (k) {
864
- var p = self.state.cursor_positions[k]
865
- var style = {
866
- position : 'absolute',
867
- left : p[0],
868
- top : p[1]
869
- }
870
- Object.keys(self.props.cursor_style).forEach(function (k) {
871
- style[k] = self.props.cursor_style[k]
872
- })
873
- cursors.push(React.createElement('div', {
874
- key : k,
875
- style : style
876
- }))
877
- })
878
- return React.createElement('div', {
879
- style : {
880
- clipPath : 'inset(0px 0px 0px 0px)'
881
- },
882
- }, React.createElement('textarea', {
883
- ref : function (t) { self.textarea_ref = t },
884
- style : this.props.textarea_style,
885
- onChange : function (e) {
886
- self.ds.on_change()
887
- self.on_text_changed()
888
- },
889
- onMouseDown : function () {
890
- setTimeout(function () { self.ds.on_change() }, 0)
891
- },
892
- onKeyDown : function () {
893
- setTimeout(function () { self.ds.on_change() }, 0)
894
- },
895
- onScroll : function () {
896
- self.on_ranges(self.ranges)
897
- }
898
- }), cursors)
899
- }
900
- })
901
- }
902
-
903
795
  function compile_coffee (coffee, filename) {
904
796
  var compiled
905
797
  try {
@@ -930,10 +822,12 @@
930
822
  return compiled
931
823
  }
932
824
  function load_client_code (code) {
933
- var dom = {}, ui = {}
934
- if (code) eval(code)
935
- else { dom = window.dom; ui = window.ui }
936
- for (var k in ui) dom[k] = dom[k] || ui[k]
825
+ // What is this function for?
826
+ var dom = {}
827
+ if (code)
828
+ eval(code)
829
+ else
830
+ dom = window.dom
937
831
  for (var widget_name in dom)
938
832
  window.dom[widget_name] = dom[widget_name]
939
833
  }
@@ -945,6 +839,11 @@
945
839
  if (scripts[i].getAttribute('type')
946
840
  in {'statebus':1, 'coffeedom':1,'statebus-js':1,
947
841
  'coffee':1, 'coffeescript':1}) {
842
+
843
+ if (!window.CoffeeScript) {
844
+ console.error('Cannot load <script type="coffee"> because coffeescript library isn\'t present')
845
+ return
846
+ }
948
847
  // Compile coffeescript to javascript
949
848
  var compiled = scripts[i].text
950
849
  if (scripts[i].getAttribute('type') !== 'statebus-js')
@@ -976,15 +875,15 @@
976
875
  return widge(props, children)
977
876
  }
978
877
 
979
- window.users_widgets = users_widgets
980
- function load_widgets () {
981
- for (var w in users_widgets) {
982
- var nodes = document.getElementsByTagName(w)
983
- for (var i=0; i<nodes.length; i++)
984
- if (!nodes[i].seen)
985
- react_render(dom_to_widget(nodes[i]), nodes[i])
986
- }
987
- }
878
+ // window.users_widgets = users_widgets
879
+ // function load_widgets () {
880
+ // for (var w in users_widgets) {
881
+ // var nodes = document.getElementsByTagName(w)
882
+ // for (var i=0; i<nodes.length; i++)
883
+ // if (!nodes[i].seen)
884
+ // react_render(dom_to_widget(nodes[i]), nodes[i])
885
+ // }
886
+ // }
988
887
 
989
888
  load_scripts()
990
889
  })()
package/extras/tests.js CHANGED
@@ -1122,23 +1122,27 @@ function setup_servers () {
1122
1122
  c.ws_mount('/*', 'statei://localhost:' + port)
1123
1123
 
1124
1124
  s.set({key: 'users',
1125
- all: [ { key: 'user/1',
1126
- name: 'mike',
1127
- email: 'toomim@gmail.com',
1128
- admin: true,
1129
- pass: '$2a$10$Ti7BgAZS8sB0Z62o2NKsIuCdmU3q9xP7jexVccTcG19Y8qpBpl/1y' }
1130
-
1131
- ,{ key: 'user/2',
1132
- name: 'j',
1133
- email: 'jtoomim@gmail.com',
1134
- admin: true,
1135
- pass: '$2a$10$Ti7BgAZS8sB0Z62o2NKsIuCdmU3q9xP7jexVccTcG19Y8qpBpl/1y' }
1136
-
1137
- ,{ key: 'user/3',
1138
- name: 'boo',
1139
- email: 'boo@gmail.com',
1140
- admin: false,
1141
- pass: '$2a$10$4UTjzf5OOGdkrCEsT.hO/.csKqf7u8mZ23ZT6stamBAWNV7u5WJuu' } ] })
1125
+ val: [ {link: 'user/1'},
1126
+ {link: 'user/2'},
1127
+ {link: 'user/3'} ] })
1128
+ s.set({ key: 'user/1', val: {
1129
+ name: 'mike',
1130
+ email: 'toomim@gmail.com',
1131
+ admin: true,
1132
+ pass: '$2a$10$Ti7BgAZS8sB0Z62o2NKsIuCdmU3q9xP7jexVccTcG19Y8qpBpl/1y'
1133
+ }})
1134
+ s.set({ key: 'user/2', val: {
1135
+ name: 'j',
1136
+ email: 'jtoomim@gmail.com',
1137
+ admin: true,
1138
+ pass: '$2a$10$Ti7BgAZS8sB0Z62o2NKsIuCdmU3q9xP7jexVccTcG19Y8qpBpl/1y'
1139
+ }})
1140
+ s.set({ key: 'user/3', val: {
1141
+ name: 'boo',
1142
+ email: 'boo@gmail.com',
1143
+ admin: false,
1144
+ pass: '$2a$10$4UTjzf5OOGdkrCEsT.hO/.csKqf7u8mZ23ZT6stamBAWNV7u5WJuu'
1145
+ }})
1142
1146
 
1143
1147
  return {s, c}
1144
1148
  }
@@ -1182,18 +1186,22 @@ test(function login (done) {
1182
1186
  c(function () {
1183
1187
  var u = c.get('/current_user')
1184
1188
  log('Current user changed!', c.label, JSON.stringify(u))
1185
- if (u.logged_in) {
1186
- log('Yay! We are logged in as', u.user.name)
1187
- c.forget()
1188
- setTimeout(function () {done()}, 200)
1189
+ if (u.val.logged_in) {
1190
+ var user = c.get(u.val.user.link)
1191
+ log('Yay! We are logged in as', u.val.user,
1192
+ 'which is loaded as', user)
1193
+ if (user.val) {
1194
+ assert(user.val.name === 'mike')
1195
+ c.forget()
1196
+ setTimeout(function () {done()}, 200)
1197
+ }
1189
1198
  } else
1190
1199
  log("Ok... we aren't logged in yet. We be patient.")
1191
1200
  })
1192
1201
 
1193
1202
  delay(200, () => {
1194
- // c.honk = user0.honk = true
1195
1203
  var u = c.get('/current_user')
1196
- u.login_as = {name: 'mike', pass: 'yeah'}
1204
+ u.val = {login_as: {name: 'mike', pass: 'yeah'}}
1197
1205
  log('Logging in')
1198
1206
  //s.honk = true
1199
1207
  c.set(u)
@@ -1207,10 +1215,10 @@ test(function wrong_password (done) {
1207
1215
 
1208
1216
  var u = c.get('/current_user')
1209
1217
  //assert(u.logged_in && u.user.name == 'mike')
1210
- u.login_as = {name: 'j', pass: 'nah'}
1218
+ u.val = {login_as: {name: 'j', pass: 'nah'}}
1211
1219
  c.set(u)
1212
1220
  delay(500, () => {
1213
- assert(!u.login_as, 'Aborted login needs to abort')
1221
+ assert(!u.val.login_as, 'Aborted login needs to abort')
1214
1222
  log('Good, the login failed.')
1215
1223
  done()
1216
1224
  })
@@ -1225,54 +1233,50 @@ test(function create_account (done) {
1225
1233
  delay(500, () => {
1226
1234
  log('Logging in')
1227
1235
  cu = c.get('/current_user')
1228
- cu.login_as = {name: 'mike', pass: 'yeah'}
1236
+ cu.val = {login_as: {name: 'mike', pass: 'yeah'}}
1229
1237
  c.set(cu)
1230
1238
  })
1231
1239
 
1232
1240
  // Log out
1233
1241
  delay(500, () => {
1234
- assert(c.get('/current_user').logged_in)
1242
+ assert(c.get('/current_user').val.logged_in)
1235
1243
  log('Logging out')
1236
- cu.logout = true; c.set(cu)
1244
+ cu.val.logout = true; c.set(cu)
1237
1245
  })
1238
1246
 
1239
1247
  // Create bob and log in as bob
1240
1248
  delay(400, () => {
1241
1249
  log('Creating bob')
1242
- assert(!cu.logged_in, '3 logged in')
1243
- cu.create_account = {name: 'bob', email: 'b@o.b', pass: 'boob'}
1250
+ assert(!cu.val.logged_in, '3 logged in')
1251
+ cu.val.create_account = {name: 'bob', email: 'b@o.b', pass: 'boob'}
1244
1252
  c.set(cu)
1245
1253
 
1246
1254
  log('Logging in as bob')
1247
- delete cu.create_account
1248
- cu.login_as = {name: 'bob', pass: 'boob'}
1255
+ delete cu.val.create_account
1256
+ cu.val.login_as = {name: 'bob', pass: 'boob'}
1249
1257
  c.set(cu)
1250
1258
  })
1251
1259
 
1252
1260
  // Log out
1253
1261
  delay(600, () => {
1254
- assert(cu.logged_in)
1255
- assert(cu.user.name === 'bob'
1256
- && cu.user.email === 'b@o.b'
1257
- && cu.user.pass === undefined
1258
- && cu.user.key.match(/\/user\/.*/),
1259
- 'Bad user', cu)
1262
+ assert(cu.val.logged_in)
1263
+ assert(cu.val.user.link === '/user/bob')
1260
1264
 
1261
1265
  log('Now let\'s log out!')
1262
- cu.logout = true; c.set(cu)
1266
+ cu.val.logout = true; c.set(cu)
1263
1267
  })
1264
1268
 
1265
1269
  // Log back in as boob
1266
1270
  delay(600, () => {
1267
1271
  log('Logging back in as boob')
1268
- assert(!cu.logged_in, 'Still logged in, as ' + cu.key)
1269
- cu.login_as = {name: 'bob', pass:'boob'}
1272
+ assert(!cu.val.logged_in, 'Still logged in, as ' + cu.key)
1273
+ cu.val.login_as = {name: 'bob', pass:'boob'}
1270
1274
  c.set(cu)
1271
1275
  })
1272
1276
 
1273
1277
  delay(600, () => {
1274
- assert(cu.logged_in)
1275
- assert(cu.user.name === 'bob')
1278
+ assert(cu.val.logged_in)
1279
+ assert(cu.val.user.link === '/user/bob')
1276
1280
  done()
1277
1281
  })
1278
1282
  })
@@ -1607,8 +1611,8 @@ if (false) {
1607
1611
 
1608
1612
  // Make stuff as user A
1609
1613
  var cu = c.get('/current_user')
1610
- c.set({key: '/current_user', create_account: {name: 'a', pass: 'a'}})
1611
- c.set({key: '/current_user', login_as: {name: 'a', pass: 'a'}})
1614
+ c.set({key: '/current_user', val: {create_account: {name: 'a', pass: 'a'}}})
1615
+ c.set({key: '/current_user', val: {login_as: {name: 'a', pass: 'a'}}})
1612
1616
  var a_closet = c.get('/user/a/foo')
1613
1617
  var a_private = c.get('/user/a/private/foo')
1614
1618
 
@@ -1620,14 +1624,14 @@ if (false) {
1620
1624
  // User A can see it
1621
1625
  delay(450, ()=> {
1622
1626
  log('1. Now curr user is', cu)
1623
- assert(cu.logged_in == true, 'not logged in')
1627
+ assert(cu.val.logged_in == true, 'not logged in')
1624
1628
  log('closet is', a_closet)
1625
1629
  assert(a_closet._ === 3, 'closet not right')
1626
1630
  assert(a_private._ === 4, 'private not right')
1627
1631
 
1628
1632
  // Set up User B
1629
- c.set({key: '/current_user', create_account: {name: 'b', pass: 'b'}})
1630
- c.set({key: '/current_user', login_as: {name: 'b', pass: 'b'}})
1633
+ c.set({key: '/current_user', val: {create_account: {name: 'b', pass: 'b'}}})
1634
+ c.set({key: '/current_user', val: {login_as: {name: 'b', pass: 'b'}}})
1631
1635
  })
1632
1636
 
1633
1637
  // User B can't see private stuff
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "statebus",
3
- "version": "7.0.1",
3
+ "version": "7.0.4",
4
4
  "description": "Synchronize state.",
5
5
  "main": "statebus.js",
6
6
  "scripts": {