braid-text 0.0.12 → 0.0.14

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.
Files changed (2) hide show
  1. package/index.js +51 -19
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -10,6 +10,8 @@ let braid_text = {
10
10
  let waiting_puts = 0
11
11
  let prev_put_p = null
12
12
 
13
+ let max_encoded_key_size = 170
14
+
13
15
  braid_text.serve = async (req, res, options = {}) => {
14
16
  options = {
15
17
  key: req.url.split('?')[0], // Default key
@@ -118,20 +120,28 @@ braid_text.serve = async (req, res, options = {}) => {
118
120
  done()
119
121
  })
120
122
  )
121
- let patches = await req.patches()
123
+ let patches = null
124
+ let ee = null
125
+ try {
126
+ patches = await req.patches()
127
+ } catch (e) { ee = e }
122
128
  await my_prev_put_p
123
129
 
124
- let body = null
125
- if (patches[0]?.unit === 'everything') {
126
- body = patches[0].content
127
- patches = null
128
- }
129
-
130
130
  try {
131
+ if (ee) throw ee
132
+
133
+ let body = null
134
+ if (patches[0]?.unit === 'everything') {
135
+ body = patches[0].content
136
+ patches = null
137
+ }
138
+
131
139
  await braid_text.put(resource, { peer, version: req.version, parents: req.parents, patches, body, merge_type: req.headers["merge-type"] })
140
+
141
+ options.put_cb(options.key, resource.doc.get())
132
142
  } catch (e) {
133
143
  console.log(`EEE= ${e}:${e.stack}`)
134
- // we couldn't apply the version, presumably because we're missing its parents.
144
+ // we couldn't apply the version, possibly because we're missing its parents,
135
145
  // we want to send a 4XX error, so the client will resend this request later,
136
146
  // hopefully after we've received the necessary parents.
137
147
 
@@ -155,11 +165,9 @@ braid_text.serve = async (req, res, options = {}) => {
155
165
  // - 428 Precondition Required
156
166
  // - pros: the name sounds right
157
167
  // - 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
158
- return done_my_turn(425, "The server is missing the parents of this version.")
168
+ return done_my_turn(425, "The server failed to apply this version.")
159
169
  }
160
170
 
161
- options.put_cb(options.key, resource.doc.get())
162
-
163
171
  return done_my_turn(200)
164
172
  }
165
173
 
@@ -493,8 +501,9 @@ braid_text.list = async () => {
493
501
  try {
494
502
  var pages = new Set()
495
503
  for (let x of await require('fs').promises.readdir(braid_text.db_folder)) {
496
- let m = x.match(/^(.*)\.\d+$/)
497
- if (m) pages.add(decode_filename(m[1]))
504
+ let k = x.replace(/\.\w+$/, '')
505
+ if (k.length <= max_encoded_key_size) pages.add(decode_filename(k))
506
+ else if (x.endsWith('.name')) pages.add(await require('fs').promises.readFile(`${braid_text.db_folder}/${x}`, { encoding: 'utf8' }))
498
507
  }
499
508
  return [...pages.keys()]
500
509
  } catch (e) { return [] }
@@ -531,7 +540,7 @@ async function get_resource(key) {
531
540
 
532
541
  async function get_files_for_key(key) {
533
542
  try {
534
- let re = new RegExp("^" + encode_filename(key).replace(/[^a-zA-Z0-9]/g, "\\$&") + "\\.\\d+$")
543
+ let re = new RegExp("^" + encode_filename(key).replace(/[^a-zA-Z0-9]/g, "\\$&") + "\\.\\w+$")
535
544
  return (await fs.promises.readdir(braid_text.db_folder))
536
545
  .filter((a) => re.test(a))
537
546
  .map((a) => `${braid_text.db_folder}/${a}`)
@@ -544,14 +553,29 @@ async function file_sync(key, process_delta, get_init) {
544
553
  let threshold = 0
545
554
 
546
555
  // Ensure the existence of db_folder
547
- try {
548
- await fs.promises.access(braid_text.db_folder);
549
- } catch (err) {
556
+ if (!file_sync.init_p) file_sync.init_p = new Promise(async done => {
550
557
  await fs.promises.mkdir(braid_text.db_folder, { recursive: true });
551
- }
558
+
559
+ // 0.0.13 -> 0.0.14
560
+ // look for files with key-encodings over max_encoded_key_size,
561
+ // and convert them using the new method
562
+ for (let x of await fs.promises.readdir(braid_text.db_folder)) {
563
+ let k = x.replace(/(_[0-9a-f]{64})?\.\w+$/, '')
564
+ if (k.length > max_encoded_key_size) {
565
+ k = decode_filename(k)
566
+
567
+ await fs.promises.rename(`${braid_text.db_folder}/${x}`, `${braid_text.db_folder}/${encode_filename(k)}${x.match(/\.\w+$/)[0]}`)
568
+ await fs.promises.writeFile(`${braid_text.db_folder}/${encode_filename(k)}.name`, k)
569
+ }
570
+ }
571
+
572
+ done()
573
+ })
574
+ await file_sync.init_p
552
575
 
553
576
  // Read existing files and sort by numbers.
554
577
  const files = (await get_files_for_key(key))
578
+ .filter(x => x.match(/\.\d+$/))
555
579
  .sort((a, b) => parseInt(a.match(/\d+$/)[0]) - parseInt(b.match(/\d+$/)[0]))
556
580
 
557
581
  // Try to process files starting from the highest number.
@@ -607,12 +631,15 @@ async function file_sync(key, process_delta, get_init) {
607
631
  try {
608
632
  console.log(`starting new db..`)
609
633
 
634
+ let encoded = encode_filename(key)
635
+ if (encoded.length > max_encoded_key_size) await fs.promises.writeFile(`${braid_text.db_folder}/${encoded}.name`, key)
636
+
610
637
  currentNumber++
611
638
  const init = get_init()
612
639
  const buffer = Buffer.allocUnsafe(4)
613
640
  buffer.writeUInt32LE(init.length, 0)
614
641
 
615
- const newFilename = `${braid_text.db_folder}/${encode_filename(key)}.${currentNumber}`
642
+ const newFilename = `${braid_text.db_folder}/${encoded}.${currentNumber}`
616
643
  await fs.promises.writeFile(newFilename, buffer)
617
644
  await fs.promises.appendFile(newFilename, init)
618
645
 
@@ -1279,6 +1306,11 @@ function encode_filename(filename) {
1279
1306
  // Encode the filename using encodeURIComponent()
1280
1307
  let encoded = encodeURIComponent(swapped)
1281
1308
 
1309
+ // Do something special with a hash if the encoding is too long
1310
+ if (encoded.length > max_encoded_key_size) {
1311
+ encoded = `${swapped.slice(0, max_encoded_key_size)}_${require('crypto').createHash('sha256').update(filename).digest('hex')}`
1312
+ }
1313
+
1282
1314
  return encoded
1283
1315
  }
1284
1316
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-text",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Library for collaborative text over http using braid.",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braidjs",