braid-text 0.2.42 → 0.2.44
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/index.js +40 -27
- package/package.json +2 -2
- package/test/test.html +178 -0
package/index.js
CHANGED
|
@@ -122,6 +122,7 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
122
122
|
} else {
|
|
123
123
|
if (!res.hasHeader("editable")) res.setHeader("Editable", "true")
|
|
124
124
|
res.setHeader("Merge-Type", merge_type)
|
|
125
|
+
res.setHeader("Current-Version", get_current_version())
|
|
125
126
|
if (req.method == "HEAD") return my_end(200)
|
|
126
127
|
|
|
127
128
|
let options = {
|
|
@@ -129,6 +130,9 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
129
130
|
version: req.version,
|
|
130
131
|
parents: req.parents,
|
|
131
132
|
merge_type,
|
|
133
|
+
accept_encoding:
|
|
134
|
+
req.headers['x-accept-encoding'] ??
|
|
135
|
+
req.headers['accept-encoding'],
|
|
132
136
|
subscribe: x => res.sendVersion(x),
|
|
133
137
|
write: (x) => res.write(x)
|
|
134
138
|
}
|
|
@@ -229,10 +233,9 @@ braid_text.get = async (key, options) => {
|
|
|
229
233
|
if (options.parents) validate_version_array(options.parents)
|
|
230
234
|
|
|
231
235
|
let resource = (typeof key == 'string') ? await get_resource(key) : key
|
|
236
|
+
var version = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
|
|
232
237
|
|
|
233
238
|
if (!options.subscribe) {
|
|
234
|
-
var version = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
|
|
235
|
-
|
|
236
239
|
if (options.transfer_encoding === 'dt') {
|
|
237
240
|
// optimization: if requesting current version
|
|
238
241
|
// pretend as if they didn't set a version,
|
|
@@ -251,7 +254,7 @@ braid_text.get = async (key, options) => {
|
|
|
251
254
|
}
|
|
252
255
|
if (options.parents) {
|
|
253
256
|
bytes = doc.getPatchSince(
|
|
254
|
-
|
|
257
|
+
dt_get_local_version(bytes, options.parents))
|
|
255
258
|
}
|
|
256
259
|
doc.free()
|
|
257
260
|
} else bytes = resource.doc.toBytes()
|
|
@@ -267,7 +270,6 @@ braid_text.get = async (key, options) => {
|
|
|
267
270
|
}
|
|
268
271
|
} else {
|
|
269
272
|
if (options.merge_type != "dt") {
|
|
270
|
-
let version = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
|
|
271
273
|
let x = { version }
|
|
272
274
|
|
|
273
275
|
if (!options.parents && !options.version) {
|
|
@@ -295,32 +297,43 @@ braid_text.get = async (key, options) => {
|
|
|
295
297
|
resource.doc = defrag_dt(resource.doc)
|
|
296
298
|
}
|
|
297
299
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
options.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
300
|
+
if (options.accept_encoding?.match(/updates\s*\((.*)\)/)?.[1].split(',').map(x=>x.trim()).includes('dt')) {
|
|
301
|
+
var bytes = resource.doc.toBytes()
|
|
302
|
+
if (options.parents) {
|
|
303
|
+
var doc = Doc.fromBytes(bytes)
|
|
304
|
+
bytes = doc.getPatchSince(
|
|
305
|
+
dt_get_local_version(bytes, options.parents))
|
|
306
|
+
doc.free()
|
|
307
|
+
}
|
|
308
|
+
options.subscribe({ encoding: 'dt', body: bytes })
|
|
307
309
|
} else {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
310
|
+
var updates = null
|
|
311
|
+
if (!options.parents && !options.version) {
|
|
312
|
+
options.subscribe({
|
|
313
|
+
version: [],
|
|
314
|
+
parents: [],
|
|
315
|
+
body: "",
|
|
316
|
+
})
|
|
311
317
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
parents
|
|
316
|
-
|
|
317
|
-
|
|
318
|
+
updates = dt_get_patches(resource.doc)
|
|
319
|
+
} else {
|
|
320
|
+
// Then start the subscription from the parents in options
|
|
321
|
+
updates = dt_get_patches(resource.doc, options.parents || options.version)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
for (let u of updates)
|
|
325
|
+
options.subscribe({
|
|
326
|
+
version: [u.version],
|
|
327
|
+
parents: u.parents,
|
|
328
|
+
patches: [{ unit: u.unit, range: u.range, content: u.content }],
|
|
329
|
+
})
|
|
318
330
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
331
|
+
// Output at least *some* data, or else chrome gets confused and
|
|
332
|
+
// thinks the connection failed. This isn't strictly necessary,
|
|
333
|
+
// but it makes fewer scary errors get printed out in the JS
|
|
334
|
+
// console.
|
|
335
|
+
if (updates.length === 0) options.write?.("\r\n")
|
|
336
|
+
}
|
|
324
337
|
|
|
325
338
|
resource.clients.add(options)
|
|
326
339
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "braid-text",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.44",
|
|
4
4
|
"description": "Library for collaborative text over http using braid.",
|
|
5
5
|
"author": "Braid Working Group",
|
|
6
6
|
"repository": "braid-org/braid-text",
|
|
7
7
|
"homepage": "https://braid.org",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@braid.org/diamond-types-node": "^2.0.0",
|
|
10
|
-
"braid-http": "~1.3.
|
|
10
|
+
"braid-http": "~1.3.79"
|
|
11
11
|
}
|
|
12
12
|
}
|
package/test/test.html
CHANGED
|
@@ -18,8 +18,20 @@
|
|
|
18
18
|
.failed {
|
|
19
19
|
background-color: #ffebee;
|
|
20
20
|
}
|
|
21
|
+
#summaryContainer {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-wrap: wrap;
|
|
24
|
+
gap: 5px;
|
|
25
|
+
margin-bottom: 20px;
|
|
26
|
+
}
|
|
27
|
+
.summaryBox {
|
|
28
|
+
width: 25px;
|
|
29
|
+
height: 25px;
|
|
30
|
+
border: 1px solid #ddd;
|
|
31
|
+
}
|
|
21
32
|
</style>
|
|
22
33
|
<script src="https://unpkg.com/braid-http@~1.3/braid-http-client.js"></script>
|
|
34
|
+
<div id="summaryContainer"></div>
|
|
23
35
|
<div id="testContainer"></div>
|
|
24
36
|
<script type=module>
|
|
25
37
|
|
|
@@ -51,20 +63,36 @@ function updateTestResult(div, passed, message, got, expected) {
|
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
65
|
|
|
66
|
+
function createSummaryBox() {
|
|
67
|
+
var summaryContainer = document.getElementById('summaryContainer')
|
|
68
|
+
const box = document.createElement('div');
|
|
69
|
+
box.className = 'summaryBox running';
|
|
70
|
+
summaryContainer.appendChild(box);
|
|
71
|
+
return box;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function updateSummaryBox(box, passed) {
|
|
75
|
+
box.className = `summaryBox ${passed ? 'passed' : passed === false ? 'failed' : 'other'}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
async function runTest(testName, testFunction, expectedResult) {
|
|
55
79
|
delay += 70
|
|
56
80
|
|
|
57
81
|
await new Promise(done => setTimeout(done, delay))
|
|
58
82
|
const div = createTestDiv(testName)
|
|
83
|
+
const summaryBox = createSummaryBox()
|
|
59
84
|
try {
|
|
60
85
|
let x = await testFunction()
|
|
61
86
|
if (x == expectedResult) {
|
|
62
87
|
updateTestResult(div, true, x)
|
|
88
|
+
updateSummaryBox(summaryBox, true)
|
|
63
89
|
} else {
|
|
64
90
|
updateTestResult(div, false, "Mismatch:", x, expectedResult)
|
|
91
|
+
updateSummaryBox(summaryBox, false)
|
|
65
92
|
}
|
|
66
93
|
} catch (error) {
|
|
67
94
|
updateTestResult(div, false, "Error:", error.message || error, expectedResult)
|
|
95
|
+
updateSummaryBox(summaryBox, false)
|
|
68
96
|
}
|
|
69
97
|
}
|
|
70
98
|
|
|
@@ -456,6 +484,135 @@ runTest(
|
|
|
456
484
|
'"hi\\u2211-1" hi∑-1 buf.byteLength:0'
|
|
457
485
|
)
|
|
458
486
|
|
|
487
|
+
runTest(
|
|
488
|
+
"test accept-encoding updates(dt) (with parents)",
|
|
489
|
+
async () => {
|
|
490
|
+
await dt_p
|
|
491
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
492
|
+
var doc = new Doc('hi')
|
|
493
|
+
doc.ins(0, 'x')
|
|
494
|
+
|
|
495
|
+
let r = await braid_fetch(`/${key}`, {
|
|
496
|
+
method: 'PUT',
|
|
497
|
+
version: ['hi-1'],
|
|
498
|
+
parents: [],
|
|
499
|
+
body: 'xy'
|
|
500
|
+
})
|
|
501
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
502
|
+
|
|
503
|
+
var a = new AbortController()
|
|
504
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
505
|
+
signal: a.signal,
|
|
506
|
+
parents: ['hi-0'],
|
|
507
|
+
subscribe: true,
|
|
508
|
+
headers: {
|
|
509
|
+
'merge-type': 'dt',
|
|
510
|
+
'X-Accept-Encoding': 'updates(dt)'
|
|
511
|
+
}
|
|
512
|
+
})
|
|
513
|
+
|
|
514
|
+
return await new Promise(done => {
|
|
515
|
+
r2.subscribe(u => {
|
|
516
|
+
doc.mergeBytes(u.body)
|
|
517
|
+
done(doc.get())
|
|
518
|
+
doc.free()
|
|
519
|
+
a.abort()
|
|
520
|
+
})
|
|
521
|
+
})
|
|
522
|
+
},
|
|
523
|
+
'xy'
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
runTest(
|
|
527
|
+
"test accept-encoding updates(dt)",
|
|
528
|
+
async () => {
|
|
529
|
+
await dt_p
|
|
530
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
531
|
+
|
|
532
|
+
let r = await braid_fetch(`/${key}`, {
|
|
533
|
+
method: 'PUT',
|
|
534
|
+
version: ['hi-1'],
|
|
535
|
+
parents: [],
|
|
536
|
+
body: 'xy'
|
|
537
|
+
})
|
|
538
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
539
|
+
|
|
540
|
+
var a = new AbortController()
|
|
541
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
542
|
+
signal: a.signal,
|
|
543
|
+
subscribe: true,
|
|
544
|
+
headers: {
|
|
545
|
+
'merge-type': 'dt',
|
|
546
|
+
'X-Accept-Encoding': 'updates(dt)'
|
|
547
|
+
}
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
var doc = new Doc('yo')
|
|
551
|
+
return await new Promise(done => {
|
|
552
|
+
r2.subscribe(u => {
|
|
553
|
+
doc.mergeBytes(u.body)
|
|
554
|
+
done(doc.get())
|
|
555
|
+
doc.free()
|
|
556
|
+
a.abort()
|
|
557
|
+
})
|
|
558
|
+
})
|
|
559
|
+
},
|
|
560
|
+
'xy'
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
runTest(
|
|
564
|
+
"test accept-encoding updates(dt), getting non-encoded update",
|
|
565
|
+
async () => {
|
|
566
|
+
await dt_p
|
|
567
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
568
|
+
|
|
569
|
+
let r = await braid_fetch(`/${key}`, {
|
|
570
|
+
method: 'PUT',
|
|
571
|
+
version: ['hi-1'],
|
|
572
|
+
parents: [],
|
|
573
|
+
body: 'xy'
|
|
574
|
+
})
|
|
575
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
576
|
+
|
|
577
|
+
var a = new AbortController()
|
|
578
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
579
|
+
signal: a.signal,
|
|
580
|
+
subscribe: true,
|
|
581
|
+
headers: {
|
|
582
|
+
'merge-type': 'dt',
|
|
583
|
+
'X-Accept-Encoding': 'updates(dt)'
|
|
584
|
+
}
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
setTimeout(async () => {
|
|
588
|
+
await braid_fetch(`/${key}`, {
|
|
589
|
+
method: 'PUT',
|
|
590
|
+
version: ['yo-0'],
|
|
591
|
+
parents: ['hi-1'],
|
|
592
|
+
patches: [{unit: 'text', range: '[2:2]', content: 'z'}]
|
|
593
|
+
})
|
|
594
|
+
}, 200)
|
|
595
|
+
|
|
596
|
+
var results = []
|
|
597
|
+
|
|
598
|
+
var doc = new Doc('yo')
|
|
599
|
+
return await new Promise(done => {
|
|
600
|
+
r2.subscribe(u => {
|
|
601
|
+
if (!u.status) {
|
|
602
|
+
doc.mergeBytes(u.body)
|
|
603
|
+
results.push(doc.get())
|
|
604
|
+
doc.free()
|
|
605
|
+
} else {
|
|
606
|
+
results.push(u.patches[0].content_text)
|
|
607
|
+
done(results.join(''))
|
|
608
|
+
a.abort()
|
|
609
|
+
}
|
|
610
|
+
})
|
|
611
|
+
})
|
|
612
|
+
},
|
|
613
|
+
'xyz'
|
|
614
|
+
)
|
|
615
|
+
|
|
459
616
|
runTest(
|
|
460
617
|
"test Version we get from PUTing",
|
|
461
618
|
async () => {
|
|
@@ -867,4 +1024,25 @@ runTest(
|
|
|
867
1024
|
'"yo-1", "hi-5", "hi-8"'
|
|
868
1025
|
)
|
|
869
1026
|
|
|
1027
|
+
runTest(
|
|
1028
|
+
"test that subscribe returns current-version header",
|
|
1029
|
+
async () => {
|
|
1030
|
+
var key = 'test-' + Math.random().toString(36).slice(2)
|
|
1031
|
+
|
|
1032
|
+
var r = await braid_fetch(`/${key}`, {
|
|
1033
|
+
method: 'PUT',
|
|
1034
|
+
version: ['hi-11'],
|
|
1035
|
+
parents: [],
|
|
1036
|
+
body: 'xyz'
|
|
1037
|
+
})
|
|
1038
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
1039
|
+
|
|
1040
|
+
var r = await braid_fetch(`/${key}`, {
|
|
1041
|
+
subscribe: true
|
|
1042
|
+
})
|
|
1043
|
+
return r.headers.get('current-version')
|
|
1044
|
+
},
|
|
1045
|
+
'"hi-11"'
|
|
1046
|
+
)
|
|
1047
|
+
|
|
870
1048
|
</script>
|