braid-text 0.2.15 → 0.2.17

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 CHANGED
@@ -80,7 +80,7 @@ braid_text.serve = async (req, res, options = {}) => {
80
80
  try {
81
81
  x = await braid_text.get(resource, { version: req.version, parents: req.parents })
82
82
  } catch (e) {
83
- return my_end(400, "The server failed to get something. The error generated was: " + e)
83
+ return my_end(500, "The server failed to get something. The error generated was: " + e)
84
84
  }
85
85
 
86
86
  res.setHeader("Version", x.version.map((x) => JSON.stringify(x)).join(", "))
@@ -116,7 +116,7 @@ braid_text.serve = async (req, res, options = {}) => {
116
116
  try {
117
117
  return await braid_text.get(resource, options)
118
118
  } catch (e) {
119
- return my_end(400, "The server failed to get something. The error generated was: " + e)
119
+ return my_end(500, "The server failed to get something. The error generated was: " + e)
120
120
  }
121
121
  }
122
122
  }
@@ -192,7 +192,7 @@ braid_text.serve = async (req, res, options = {}) => {
192
192
  // - cons: typically implies that the request was missing an http conditional field like If-Match. that is to say, it implies that the request is missing a precondition, not that the server is missing a precondition
193
193
  return done_my_turn(425, e.message)
194
194
  } else {
195
- return done_my_turn(400, "The server failed to apply this version. The error generated was: " + e)
195
+ return done_my_turn(500, "The server failed to apply this version. The error generated was: " + e)
196
196
  }
197
197
  }
198
198
 
@@ -219,17 +219,14 @@ braid_text.get = async (key, options) => {
219
219
  let resource = (typeof key == 'string') ? await get_resource(key) : key
220
220
 
221
221
  if (!options.subscribe) {
222
- let doc = resource.doc
223
- if (options.version || options.parents) doc = dt_get(doc, options.version || options.parents)
224
-
225
- let ret = {
226
- version: doc.getRemoteVersion().map((x) => x.join("-")).sort(),
227
- body: doc.get()
228
- }
229
-
230
- if (options.version || options.parents) doc.free()
231
-
232
- return ret
222
+ return options.version || options.parents ?
223
+ {
224
+ version: options.version || options.parents,
225
+ body: dt_get_string(resource.doc, options.version || options.parents)
226
+ } : {
227
+ version: resource.doc.getRemoteVersion().map((x) => x.join("-")).sort(),
228
+ body: resource.doc.get()
229
+ }
233
230
  } else {
234
231
  if (options.merge_type != "dt") {
235
232
  let version = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
@@ -580,6 +577,34 @@ braid_text.put = async (key, options) => {
580
577
  await resource.db_delta(resource.doc.getPatchSince(v_before))
581
578
  }
582
579
 
580
+ braid_text.revert = async (key, actor, seq) => {
581
+ var resource = (typeof key == 'string') ? await get_resource(key) : key
582
+
583
+ // get version without actor-seq,
584
+ // and update actor_seqs
585
+ var v = []
586
+ for (var [a, s] of Object.entries(resource.actor_seqs)) {
587
+ if (a !== actor) v.push(`${a}-${s}`)
588
+ else {
589
+ if (s < seq) return // nothing to do
590
+ else if (seq > 0) {
591
+ v.push(`${a}-${seq - 1}`)
592
+ resource.actor_seqs[actor] = seq - 1
593
+ } else delete resource.actor_seqs[actor]
594
+ }
595
+ }
596
+
597
+ // revert dt
598
+ var old_doc = resource.doc
599
+ resource.doc = dt_get(resource.doc, v)
600
+ old_doc.free()
601
+
602
+ resource.val = resource.doc.get()
603
+
604
+ // save it
605
+ await resource.db_delta()
606
+ }
607
+
583
608
  braid_text.list = async () => {
584
609
  try {
585
610
  if (braid_text.db_folder) {
@@ -745,7 +770,8 @@ async function file_sync(key, process_delta, get_init) {
745
770
  return {
746
771
  change: async (bytes) => {
747
772
  await (chain = chain.then(async () => {
748
- currentSize += bytes.length + 4 // we account for the extra 4 bytes for uint32
773
+ if (!bytes) currentSize = threshold
774
+ else currentSize += bytes.length + 4 // we account for the extra 4 bytes for uint32
749
775
  const filename = `${braid_text.db_folder}/${encoded}.${currentNumber}`
750
776
  if (currentSize < threshold) {
751
777
  if (braid_text.verbose) console.log(`appending to db..`)
@@ -790,14 +816,18 @@ async function file_sync(key, process_delta, get_init) {
790
816
  //////////////////////////////////////////////////////////////////
791
817
 
792
818
  function dt_len(doc, version) {
793
- let bytes = doc.toBytes()
794
- let oplog = OpLog.fromBytes(bytes)
795
- let [_agents, versions, _parentss] = dt_parse([...bytes])
819
+ return count_code_points(dt_get_string(doc, version))
820
+ }
796
821
 
797
- let frontier = new Set(version)
822
+ function dt_get_string(doc, version) {
823
+ var bytes = doc.toBytes()
824
+ var oplog = OpLog.fromBytes(bytes)
825
+ var [_agents, versions, _parentss] = dt_parse([...bytes])
798
826
 
799
- let local_version = []
800
- for (let i = 0; i < versions.length; i++) {
827
+ var frontier = new Set(version)
828
+
829
+ var local_version = []
830
+ for (var i = 0; i < versions.length; i++) {
801
831
  var v = versions[i].join("-")
802
832
  if (frontier.has(v)) {
803
833
  local_version.push(i)
@@ -807,13 +837,13 @@ function dt_len(doc, version) {
807
837
 
808
838
  if (frontier.size) throw new Error(`version not found: ${version}`)
809
839
 
810
- let b = new Branch()
840
+ var b = new Branch()
811
841
  b.merge(oplog, new Uint32Array(local_version))
812
- let len = count_code_points(b.get())
842
+ var s = b.get()
813
843
  b.free()
814
844
 
815
845
  oplog.free()
816
- return len
846
+ return s
817
847
  }
818
848
 
819
849
  function dt_get(doc, version, agent = null) {
@@ -1741,4 +1771,6 @@ braid_text.dt_get_patches = dt_get_patches
1741
1771
  braid_text.dt_parse = dt_parse
1742
1772
  braid_text.dt_create_bytes = dt_create_bytes
1743
1773
 
1774
+ braid_text.decode_version = decode_version
1775
+
1744
1776
  module.exports = braid_text
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-text",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "Library for collaborative text over http using braid.",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braid-text",
package/test/server.js CHANGED
@@ -46,5 +46,5 @@ var server = require("http").createServer(async (req, res) => {
46
46
  })
47
47
 
48
48
  server.listen(port, () => {
49
- console.log(`server started on port ${port}`)
49
+ console.log(`serving: http://localhost:${port}/test.html`)
50
50
  })
package/test/test.js CHANGED
@@ -12,18 +12,43 @@ process.on("uncaughtException", (x) =>
12
12
 
13
13
  braid_text.db_folder = null
14
14
 
15
+ async function test_revert() {
16
+ braid_text.db_folder = './braid-text-db'
17
+ var key = Math.random().toString(36).slice(2)
18
+ await braid_text.put(key, {version: ['a-0'], body: 'A'})
19
+ await braid_text.put(key, {version: ['a-1'], parents: ['a-0'], patches: [{range: '[1:1]', content: 'B'}]})
20
+ await braid_text.revert(key, 'a', 1)
21
+ delete braid_text.cache[key]
22
+ var {version, body} = await braid_text.get(key, {})
23
+ if (version[0] != 'a-0') throw new Error('revert error: wrong version')
24
+ if (body != 'A') throw new Error('revert error: wrong text')
25
+
26
+ await braid_text.put(key, {version: ['b-0'], parents: ['a-0'], patches: [{range: '[1:1]', content: 'C'}]})
27
+ if ('AC' !== await braid_text.get(key)) throw new Error('revert error: wrong text')
28
+ await braid_text.revert(key, 'b', 0)
29
+ if ('A' !== await braid_text.get(key)) throw new Error('revert error: wrong text')
30
+ delete braid_text.cache[key]
31
+ var {version, body} = await braid_text.get(key, {})
32
+ if (version[0] != 'a-0') throw new Error('revert error: wrong version')
33
+ if (body != 'A') throw new Error('revert error: wrong text')
34
+
35
+ braid_text.db_folder = null
36
+ }
37
+
15
38
  async function main() {
16
39
  let best_seed = NaN
17
40
  let best_n = Infinity
18
41
  let base = Math.floor(Math.random() * 10000000)
19
42
  let st = Date.now()
20
43
 
44
+ await test_revert()
45
+
21
46
  let og_log = console.log
22
47
  console.log = () => {}
23
48
  for (let t = 0; t < 10000; t++) {
24
49
  let seed = base + t
25
50
  // for (let t = 0; t < 1; t++) {
26
- // let seed = 7572861
51
+ // let seed = 7375800
27
52
 
28
53
  og_log(`t = ${t}, seed = ${seed}, best_n = ${best_n} @ ${best_seed}`)
29
54
  Math.randomSeed(seed)
@@ -53,6 +78,11 @@ async function main() {
53
78
  let dt_to_braid = async (doc, key) => {
54
79
  await braid_text.get(key, {})
55
80
  for (let x of dt_get_patches(doc)) {
81
+ var resource = await braid_text.get_resource(key)
82
+ var [actor, seq] = braid_text.decode_version(x.version)
83
+ var pre_seq = resource.actor_seqs[actor]
84
+ var old_text = await braid_text.get(key)
85
+
56
86
  console.log(`x = `, x)
57
87
  let y = {
58
88
  merge_type: 'dt',
@@ -67,6 +97,12 @@ async function main() {
67
97
  await braid_text.put(key, y)
68
98
  y.validate_already_seen_versions = true
69
99
  await braid_text.put(key, y)
100
+
101
+ // test revert
102
+ await braid_text.revert(key, actor, (pre_seq ?? -1) + 1)
103
+ var new_text = await braid_text.get(key)
104
+ if (old_text !== new_text) throw new Error('revert failed!')
105
+ await braid_text.put(key, y)
70
106
  }
71
107
  }
72
108
  await dt_to_braid(doc, 'doc')
@@ -196,12 +232,6 @@ function getRandomCharacter() {
196
232
  return characters[randomIndex];
197
233
  }
198
234
 
199
- function decode_version(v) {
200
- let m = v.match(/^(.*)-(\d+)$/s)
201
- if (!m) throw new Error(`invalid actor-seq version: ${v}`)
202
- return [m[1], parseInt(m[2])]
203
- }
204
-
205
235
  /////////
206
236
 
207
237
  // the next two functions added by me