statebus 6.1.22 → 7.0.2
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/{client.js → clients.js} +184 -130
- package/extras/tests.js +292 -412
- package/package.json +10 -3
- package/{server.js → servers.js} +285 -333
- package/statebus.js +297 -620
- package/extras/coffee.js +0 -12
- package/extras/dash.coffee +0 -302
- package/extras/diffsync.js +0 -1462
- package/extras/getCaretCoordinates.js +0 -141
- package/extras/react.js +0 -18147
- package/extras/sockjs.js +0 -27
package/extras/dash.coffee
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
window.dashable_keys = []
|
|
2
|
-
dashable = (k) ->
|
|
3
|
-
return true
|
|
4
|
-
for k2 of dashable_keys
|
|
5
|
-
if k == k2 or (k2.match(/\*$/) and k2.substr(k2.length-1) == k.substr(k2.length-1))
|
|
6
|
-
return true
|
|
7
|
-
return false
|
|
8
|
-
|
|
9
|
-
parse_key = (key) ->
|
|
10
|
-
word = "([^/]+)"
|
|
11
|
-
# Matching things like: "/new/name/number"
|
|
12
|
-
# or: "/name/number"
|
|
13
|
-
# or: "/name"
|
|
14
|
-
# or: "name/number"
|
|
15
|
-
# or: "name"
|
|
16
|
-
# ... and you can optionally include a final slash.
|
|
17
|
-
regexp = new RegExp("(/)?(new/)?#{word}(/#{word})?(/)?")
|
|
18
|
-
m = key.match(regexp)
|
|
19
|
-
if not m
|
|
20
|
-
return null
|
|
21
|
-
|
|
22
|
-
[has_match, server_owned, is_new, name, tmp1, number, tmp2] = m
|
|
23
|
-
owner = if server_owned then 'server' else 'client'
|
|
24
|
-
return has_match and {owner, 'new': is_new, name, number}
|
|
25
|
-
|
|
26
|
-
dom.STATE_DASH = ->
|
|
27
|
-
dash = bus.fetch('state_dash')
|
|
28
|
-
|
|
29
|
-
if !dash.on?
|
|
30
|
-
dash.on = false
|
|
31
|
-
dash.selected = {owner: null, name: null, number: null}
|
|
32
|
-
dash.filter = null
|
|
33
|
-
|
|
34
|
-
if dash.filter?.match(/idkfa/) or dash.filter?.match(/idmap/)
|
|
35
|
-
dash.on = false
|
|
36
|
-
dash.filter = ''
|
|
37
|
-
bus.save(dash)
|
|
38
|
-
|
|
39
|
-
if not dash.on
|
|
40
|
-
return DIV null, ''
|
|
41
|
-
|
|
42
|
-
url_tree = (cache) ->
|
|
43
|
-
# The key tree looks like:
|
|
44
|
-
#
|
|
45
|
-
# {server: {thing: [obj1, obj2], shing: [obj1, obj2], ...}
|
|
46
|
-
# client: {dong: [obj1, ...]}}
|
|
47
|
-
#
|
|
48
|
-
# And objects without a number, like '/shong' will go on:
|
|
49
|
-
# key_tree.server.shong[null]
|
|
50
|
-
tree = {server: {}, client: {}}
|
|
51
|
-
|
|
52
|
-
add_key = (key) ->
|
|
53
|
-
p = parse_key(key)
|
|
54
|
-
if not p
|
|
55
|
-
console.log('The state dash can\'t deal with key', key); return null
|
|
56
|
-
|
|
57
|
-
if not p.name in dashable_keys then return null
|
|
58
|
-
|
|
59
|
-
tree[p.owner][p.name] ||= []
|
|
60
|
-
tree[p.owner][p.name][p.number or null] = bus.fetch(key)
|
|
61
|
-
|
|
62
|
-
for key of cache
|
|
63
|
-
add_key(key)
|
|
64
|
-
return tree
|
|
65
|
-
|
|
66
|
-
search_results = get_search_results()
|
|
67
|
-
cache = search_results.matches
|
|
68
|
-
tree = url_tree(cache)
|
|
69
|
-
|
|
70
|
-
first_key = (cache) ->
|
|
71
|
-
for key of cache
|
|
72
|
-
reject_name = dash.selected.name and parse_key(key).name != dash.selected.name
|
|
73
|
-
reject_numb = dash.selected.number and parse_key(key).number != dash.selected.number
|
|
74
|
-
if !reject_name and !reject_numb
|
|
75
|
-
return key
|
|
76
|
-
return null
|
|
77
|
-
|
|
78
|
-
best_guess = first_key(search_results.key_matches) or \
|
|
79
|
-
first_key(search_results.data_matches)
|
|
80
|
-
|
|
81
|
-
cluster_rows = (keys) ->
|
|
82
|
-
clusters = {}
|
|
83
|
-
for key in keys
|
|
84
|
-
fields = JSON.stringify(Object.keys(cache[key]))
|
|
85
|
-
clusters[fields] = clusters[fields] or []
|
|
86
|
-
clusters[fields].push(key)
|
|
87
|
-
return clusters
|
|
88
|
-
|
|
89
|
-
filter_to = (e) ->
|
|
90
|
-
dash.filter = e.target.value
|
|
91
|
-
if dash.filter.length == 0
|
|
92
|
-
dash.filter = null
|
|
93
|
-
bus.save(dash)
|
|
94
|
-
true
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
DIV className: 'state_dash', style: this.props.style,
|
|
98
|
-
React.DOM.style({dangerouslySetInnerHTML: {__html:
|
|
99
|
-
"""
|
|
100
|
-
.state_dash {
|
|
101
|
-
position: fixed;
|
|
102
|
-
margin: 20px;
|
|
103
|
-
z-index: 10000;
|
|
104
|
-
top: 0;
|
|
105
|
-
left: 0;
|
|
106
|
-
}
|
|
107
|
-
.state_dash .left, .state_dash .right, .state_dash .top {
|
|
108
|
-
background-color: #eee;
|
|
109
|
-
overflow-wrap: break-word;
|
|
110
|
-
padding: 10px;
|
|
111
|
-
vertical-align: top;
|
|
112
|
-
}
|
|
113
|
-
.state_dash .left { min-width: 40px; max-width: 140px; }
|
|
114
|
-
.state_dash .right { left: 180px; position: absolute; white-space: nowrap; }
|
|
115
|
-
.state_dash .top { max-width: 100%; margin: 20px 0; }
|
|
116
|
-
|
|
117
|
-
.string { color: green; }
|
|
118
|
-
.number { color: darkorange; }
|
|
119
|
-
.boolean { color: blue; }
|
|
120
|
-
.null { color: magenta; }
|
|
121
|
-
.key { color: red; }
|
|
122
|
-
|
|
123
|
-
.cell {
|
|
124
|
-
width: 150px;
|
|
125
|
-
height: 26px;
|
|
126
|
-
border: 1px solid grey;
|
|
127
|
-
padding: 2px;
|
|
128
|
-
display: inline-block;
|
|
129
|
-
white-space: nowrap;
|
|
130
|
-
overflow: hidden;
|
|
131
|
-
text-overflow: clip;
|
|
132
|
-
margin: 0;
|
|
133
|
-
}
|
|
134
|
-
"""}})
|
|
135
|
-
|
|
136
|
-
# Render the object
|
|
137
|
-
# PRE className: 'right', ref: 'json_preview',
|
|
138
|
-
# JSON.stringify(arest.cache[best_guess], undefined, 3)
|
|
139
|
-
DIV className: 'right',
|
|
140
|
-
# Next: go through the list, cluster those that fit the same
|
|
141
|
-
# schema, and display a table for each.
|
|
142
|
-
if dash.selected.name
|
|
143
|
-
selected_keys = (key for key of cache when parse_key(key).name == dash.selected.name)
|
|
144
|
-
clusters = cluster_rows(selected_keys)
|
|
145
|
-
for fieldset of clusters
|
|
146
|
-
# Print each table
|
|
147
|
-
DIV null,
|
|
148
|
-
# Print the table header
|
|
149
|
-
for field in JSON.parse(fieldset)
|
|
150
|
-
DIV
|
|
151
|
-
key: field
|
|
152
|
-
style: {fontWeight: 'bold', borderColor: '#eee'}
|
|
153
|
-
className: 'cell'
|
|
154
|
-
field
|
|
155
|
-
|
|
156
|
-
# Print the table body
|
|
157
|
-
for key in clusters[fieldset]
|
|
158
|
-
row = cache[key]
|
|
159
|
-
DIV key: key,
|
|
160
|
-
for field of row
|
|
161
|
-
DIV
|
|
162
|
-
className: 'cell'
|
|
163
|
-
key: field
|
|
164
|
-
onClick: do (key, field) => (evt) =>
|
|
165
|
-
@local.editing = {key_:key, field:field}
|
|
166
|
-
bus.save(@local)
|
|
167
|
-
setTimeout(=> @refs.dash_input.getDOMNode().focus())
|
|
168
|
-
if (@local.editing \
|
|
169
|
-
and @local.editing.key_ == key \
|
|
170
|
-
and @local.editing.field == field)
|
|
171
|
-
SPAN null,
|
|
172
|
-
TEXTAREA
|
|
173
|
-
key: field
|
|
174
|
-
type: 'text'
|
|
175
|
-
ref: 'dash_input'
|
|
176
|
-
defaultValue: JSON.stringify(row[field])
|
|
177
|
-
onChange: (event) =>
|
|
178
|
-
try
|
|
179
|
-
val = JSON.parse(@refs.dash_input.getDOMNode().value)
|
|
180
|
-
cache[@local.editing.key_][@local.editing.field] = val
|
|
181
|
-
bus.save(cache[@local.editing.key_])
|
|
182
|
-
event.stopPropagation()
|
|
183
|
-
|
|
184
|
-
delete @local.editing.error; bus.save(@local)
|
|
185
|
-
catch e
|
|
186
|
-
@local.editing.error = true; bus.save(@local)
|
|
187
|
-
onBlur: (event) =>
|
|
188
|
-
delete @local.editing; bus.save(@local)
|
|
189
|
-
style:
|
|
190
|
-
position: 'absolute'
|
|
191
|
-
backgroundColor: '#faa' if @local.editing.error
|
|
192
|
-
# INPUT
|
|
193
|
-
# type: 'submit'
|
|
194
|
-
# onClick: (event) =>
|
|
195
|
-
# try
|
|
196
|
-
# val = JSON.parse(@refs.dash_input.getDOMNode().value)
|
|
197
|
-
# cache[@local.editing.key_][@local.editing.field] = val
|
|
198
|
-
# bus.save(cache[@local.editing.key_])
|
|
199
|
-
# c = bus.fetch('component/1')
|
|
200
|
-
# delete c.editing
|
|
201
|
-
# bus.save(c)
|
|
202
|
-
# event.stopPropagation()
|
|
203
|
-
# catch e
|
|
204
|
-
# @local.editing.error = true
|
|
205
|
-
# bus.save(@local)
|
|
206
|
-
# style:
|
|
207
|
-
# position: 'absolute'
|
|
208
|
-
# marginTop: 30
|
|
209
|
-
|
|
210
|
-
JSON.stringify(row[field])
|
|
211
|
-
|
|
212
|
-
# Render the top (name) menu
|
|
213
|
-
DIV className: 'left', #onMouseLeave: reset_selection,
|
|
214
|
-
INPUT
|
|
215
|
-
ref: 'search'
|
|
216
|
-
className: 'search'
|
|
217
|
-
onChange: filter_to
|
|
218
|
-
onMouseEnter: reset_selection
|
|
219
|
-
|
|
220
|
-
for owner in ['client', 'server']
|
|
221
|
-
prefix = (owner == 'server') and '/' or ''
|
|
222
|
-
names = (n for n of tree[owner])
|
|
223
|
-
DIV {key: owner},
|
|
224
|
-
for name in names.sort()
|
|
225
|
-
do (owner, name) ->
|
|
226
|
-
f = -> dash.selected={owner, name, number:null}; bus.save(dash)
|
|
227
|
-
style = (name == dash.selected.name) and {'background-color':'#aaf'} or {}
|
|
228
|
-
DIV onMouseEnter: f, key: name, style: style,
|
|
229
|
-
prefix + name
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
recent_keys = [0,0,0,0,0]
|
|
233
|
-
|
|
234
|
-
dash_initialized = false
|
|
235
|
-
window.addEventListener('DOMContentLoaded', ->
|
|
236
|
-
document.addEventListener "keypress", (e) =>
|
|
237
|
-
key = (e and e.keyCode) or e.keyCode
|
|
238
|
-
recent_keys.push(key)
|
|
239
|
-
recent_keys = recent_keys.slice(1)
|
|
240
|
-
|
|
241
|
-
# console.log('recent keys:', recent_keys)
|
|
242
|
-
if key==4 or "#{recent_keys}" == "#{[105, 100, 109, 97, 112]}" \ # idmap
|
|
243
|
-
or "#{recent_keys}" == "#{[105, 100, 107, 102, 97]}" # idkfa
|
|
244
|
-
dash = bus.fetch('state_dash')
|
|
245
|
-
if dash.on
|
|
246
|
-
dash.on = false
|
|
247
|
-
else
|
|
248
|
-
dash.on = true
|
|
249
|
-
bus.save(dash)
|
|
250
|
-
# setTimeout =>
|
|
251
|
-
# console.log @refs
|
|
252
|
-
# @refs.search.getDOMNode().focus()
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
get_search_results = ->
|
|
256
|
-
# Returns two filtered views of the cache:
|
|
257
|
-
#
|
|
258
|
-
# { key_matches: {...a cache filtered to matching keys... }
|
|
259
|
-
# data_matches: {...a cache filtered to matching data...} }
|
|
260
|
-
|
|
261
|
-
dash = bus.fetch('state_dash')
|
|
262
|
-
matches = {}
|
|
263
|
-
key_matches = {}
|
|
264
|
-
data_matches = {}
|
|
265
|
-
if dash.filter
|
|
266
|
-
for key of bus.cache
|
|
267
|
-
if key.match(dash.filter)
|
|
268
|
-
matches[key] = bus.cache[key]
|
|
269
|
-
key_matches[key] = bus.cache[key]
|
|
270
|
-
if JSON.stringify(bus.cache[key]).match(dash.filter)
|
|
271
|
-
matches[key] = bus.cache[key]
|
|
272
|
-
data_matches[key] = bus.cache[key]
|
|
273
|
-
else
|
|
274
|
-
matches = key_matches = data_matches = bus.cache
|
|
275
|
-
|
|
276
|
-
return {matches, key_matches, data_matches}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
# componentDidUpdate: () ->
|
|
280
|
-
# el = @refs.json_preview.getDOMNode()
|
|
281
|
-
# el.innerHTML = rainbows(el.innerHTML)
|
|
282
|
-
|
|
283
|
-
reset_selection = () ->
|
|
284
|
-
dash = bus.fetch('state_dash')
|
|
285
|
-
dash.selected = {owner: null, name: null, number: null}
|
|
286
|
-
bus.save(dash)
|
|
287
|
-
|
|
288
|
-
rainbows = (json) ->
|
|
289
|
-
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
290
|
-
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, (match) ->
|
|
291
|
-
cls = 'number'
|
|
292
|
-
if (/^"/.test(match))
|
|
293
|
-
if (/:$/.test(match))
|
|
294
|
-
cls = 'key'
|
|
295
|
-
else
|
|
296
|
-
cls = 'string';
|
|
297
|
-
else if (/true|false/.test(match))
|
|
298
|
-
cls = 'boolean'
|
|
299
|
-
else if (/null/.test(match))
|
|
300
|
-
cls = 'null';
|
|
301
|
-
|
|
302
|
-
return "<span class=\"#{cls}\">#{match}</span>")
|