braidfs 0.0.132 → 0.0.133

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 +112 -191
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var { diff_main } = require(`${__dirname}/diff.js`),
4
4
  braid_text = require("braid-text"),
5
+ braid_blob = require("braid-blob"),
5
6
  braid_fetch = require('braid-http').fetch
6
7
 
7
8
  // Helper function to check if a file is binary based on its extension
@@ -27,6 +28,8 @@ var braidfs_config_dir = `${sync_base}/.braidfs`,
27
28
  braidfs_config_file = `${braidfs_config_dir}/config`,
28
29
  sync_base_meta = `${braidfs_config_dir}/proxy_base_meta`
29
30
  braid_text.db_folder = `${braidfs_config_dir}/braid-text-db`
31
+ braid_blob.db_folder = { read: () => {}, write: () => {}, delete: () => {} }
32
+ braid_blob.meta_folder = `${braidfs_config_dir}/braid-blob-meta`
30
33
  var trash = `${braidfs_config_dir}/trash`
31
34
  var temp_folder = `${braidfs_config_dir}/temp`
32
35
 
@@ -417,6 +420,7 @@ async function sync_url(url) {
417
420
  url = normalized_url
418
421
 
419
422
  await braid_text.db_folder_init()
423
+ await braid_blob.init()
420
424
 
421
425
  var is_external_link = url.match(/^https?:\/\//),
422
426
  path = is_external_link ? url.replace(/^https?:\/\//, '') : url,
@@ -451,7 +455,10 @@ async function sync_url(url) {
451
455
  await self.disconnect?.()
452
456
  await wait_promise
453
457
 
454
- await braid_text.delete(url)
458
+ if (self.merge_type === 'dt')
459
+ await braid_text.delete(url)
460
+ else if (self.merge_type === 'aww')
461
+ await braid_blob.delete(url)
455
462
 
456
463
  try {
457
464
  console.log(`trying to delete: ${meta_path}`)
@@ -520,12 +527,14 @@ async function sync_url(url) {
520
527
  await require('fs').promises.writeFile(meta_path, JSON.stringify({
521
528
  merge_type: self.merge_type,
522
529
  peer: self.peer,
523
- version: self.version,
524
530
  file_mtimeNs_str: self.file_mtimeNs_str
525
531
  }))
526
532
  }
527
533
 
528
- await within_fiber(url, async () => {
534
+ self.file_mtimeNs_str = null
535
+ self.file_read_only = null
536
+
537
+ await within_fiber(fullpath, async () => {
529
538
  try {
530
539
  Object.assign(self, JSON.parse(
531
540
  await require('fs').promises.readFile(meta_path, 'utf8')))
@@ -533,219 +542,131 @@ async function sync_url(url) {
533
542
  if (freed) return
534
543
 
535
544
  if (!self.peer) self.peer = Math.random().toString(36).slice(2)
536
-
537
- // create file if it doesn't exist
538
- var fullpath = await get_fullpath()
539
- if (freed) return
540
- if (!(await file_exists(fullpath))) {
541
- if (freed) return
542
- await wait_on(require('fs').promises.writeFile(fullpath, ''))
543
- if (freed) return
544
- var stat = await require('fs').promises.stat(fullpath, { bigint: true })
545
- if (freed) return
546
- self.file_mtimeNs_str = '' + stat.mtimeNs
547
- self.last_touch = Date.now()
548
- }
549
- if (freed) return
550
-
551
- await save_meta()
552
545
  })
553
546
  if (freed) return
554
547
 
555
- var waitTime = 1
556
- var last_connect_timer = null
548
+ self.signal_file_needs_reading = async () => {
549
+ await within_fiber(fullpath, async () => {
550
+ try {
551
+ if (freed) return
557
552
 
558
- self.signal_file_needs_reading = () => {}
553
+ var fullpath = await get_fullpath()
554
+ if (freed) return
559
555
 
560
- connect()
561
- async function connect() {
562
- if (freed) return
563
- if (last_connect_timer) return
556
+ var stat = await require('fs').promises.stat(fullpath, { bigint: true })
557
+ if (freed) return
564
558
 
565
- var closed = false
566
- var prev_disconnect = self.disconnect
567
- self.disconnect = async () => {
568
- if (closed) return
569
- closed = true
570
- reconnect_rate_limiter.on_diss(url)
571
- for (var a of aborts) a.abort()
572
- aborts.clear()
573
- }
574
- self.reconnect = connect
575
-
576
- await prev_disconnect?.()
577
- if (freed || closed) return
578
-
579
- await reconnect_rate_limiter.get_turn(url)
580
- if (freed || closed) return
581
-
582
- function retry(e) {
583
- if (freed || closed) return
584
- var p = self.disconnect()
585
-
586
- var delay = waitTime * (config.retry_delay_ms ?? 1000)
587
- console.log(`reconnecting in ${(delay / 1000).toFixed(2)}s: ${url} after error: ${e}`)
588
- last_connect_timer = setTimeout(async () => {
589
- await p
590
- last_connect_timer = null
591
- connect()
592
- }, delay)
593
- waitTime = Math.min(waitTime + 1, 3)
594
- }
559
+ if (self.file_mtimeNs_str !== '' + stat.mtimeNs) {
560
+ var data = await require('fs').promises.readFile(fullpath, { encoding: 'utf8' })
561
+ if (freed) return
595
562
 
596
- try {
597
- var a = new AbortController()
598
- aborts.add(a)
599
-
600
- var fork_point
601
- if (self.version) {
602
- // Check if server has our version
603
- var r = await braid_fetch(url, {
604
- signal: a.signal,
605
- method: "HEAD",
606
- version: ['' + self.version]
607
- })
608
- if (r.ok) fork_point = ['' + self.version]
563
+ await braid_blob.put(url, data, { skip_write: true })
564
+ if (freed) return
565
+
566
+ self.file_mtimeNs_str = '' + stat.mtimeNs
567
+ await save_meta()
568
+ }
569
+ } catch (e) {
570
+ if (e.code !== 'ENOENT') throw e
609
571
  }
572
+ })
573
+ }
574
+ await self.signal_file_needs_reading()
610
575
 
611
- var res = await braid_fetch(url, {
612
- signal: a.signal,
613
- headers: {
614
- ...(x => x && {Cookie: x})(config.cookies?.[new URL(url).hostname]),
615
- },
616
- subscribe: true,
617
- heartbeats: 120,
618
- peer: self.peer,
619
- parents: fork_point || []
620
- })
621
- if (freed || closed) return
622
-
623
- if (res.status < 200 || res.status >= 300) return retry(new Error(`unexpected status: ${res.status}`))
624
-
625
- if (res.status !== 209)
626
- return log_error(`Can't sync ${url} -- got bad response ${res.status} from server (expected 209)`)
627
-
628
- self.file_read_only = res.headers.get('editable') === 'false'
576
+ var db = {
577
+ read: async (_key) => {
578
+ return await within_fiber(fullpath, async () => {
579
+ var fullpath = await get_fullpath()
580
+ if (freed) return
629
581
 
630
- await wait_on(within_fiber(url, async () => {
582
+ try {
583
+ return await require('fs').promises.readFile(fullpath)
584
+ } catch (e) {
585
+ if (e.code === 'ENOENT') return null
586
+ throw e
587
+ }
588
+ })
589
+ },
590
+ write: async (_key, data) => {
591
+ return await within_fiber(fullpath, async () => {
631
592
  var fullpath = await get_fullpath()
632
- if (freed || closed) return
593
+ if (freed) return
633
594
 
634
- await set_read_only(fullpath, self.file_read_only)
635
- }))
595
+ try {
596
+ var temp = `${temp_folder}/${Math.random().toString(36).slice(2)}`
597
+ await require('fs').promises.writeFile(temp, data)
598
+ if (freed) return
636
599
 
637
- console.log(`connected to ${url}${self.file_read_only ? ' (readonly)' : ''}`)
600
+ var stat = await require('fs').promises.stat(temp, { bigint: true })
601
+ if (freed) return
638
602
 
639
- reconnect_rate_limiter.on_conn(url)
640
-
641
- res.subscribe(async update => {
642
- if (freed || closed) return
643
- if (update.version.length === 0) return
644
- if (update.version.length !== 1) throw 'unexpected'
645
- var version = 1*update.version[0]
646
- if (!update.body) return
647
-
648
- if (self.version != null &&
649
- version <= self.version) return
650
- self.version = version
651
-
652
- await within_fiber(url, async () => {
653
- var fullpath = await get_fullpath()
654
- if (freed || closed) return
655
-
656
- await wait_on(set_read_only(fullpath, false))
657
- if (freed || closed) return
658
- await wait_on(require('fs').promises.writeFile(fullpath, update.body))
659
- if (freed || closed) return
660
- await wait_on(set_read_only(fullpath, self.file_read_only))
661
- if (freed || closed) return
662
-
663
- var stat = await require('fs').promises.stat(fullpath, { bigint: true })
664
- if (freed || closed) return
665
- self.file_mtimeNs_str = '' + stat.mtimeNs
666
- self.last_touch = Date.now()
603
+ await require('fs').promises.rename(temp, fullpath)
604
+ if (freed) return
667
605
 
606
+ self.file_mtimeNs_str = '' + stat.mtimeNs
668
607
  await save_meta()
669
- })
670
- }, retry)
671
-
672
- async function send_file(fullpath) {
673
- var body = await require('fs').promises.readFile(fullpath)
674
- if (freed || closed) return
675
-
676
- try {
677
- var a = new AbortController()
678
- aborts.add(a)
679
- var r = await braid_fetch(url, {
680
- method: 'PUT',
681
- signal: a.signal,
682
- version: ['' + self.version],
683
- body,
684
- headers: {
685
- ...(x => x && {Cookie: x})(config.cookies?.[new URL(url).hostname])
686
- },
687
- })
688
- if (freed || closed) return
689
-
690
- // if we're not authorized,
691
- if (r.status == 401 || r.status == 403) {
692
- // then revert it
693
- console.log(`access denied: reverting local edits`)
694
- unsync_url(url)
695
- sync_url(url)
696
- } else if (!r.ok) {
697
- retry(new Error(`unexpected PUT status: ${r.status}`))
698
- }
699
- } catch (e) { retry(e) }
700
- }
701
-
702
- // if what we have now is newer than what the server has,
703
- // go ahead and send it
704
- await within_fiber(url, async () => {
705
- if (freed || closed) return
608
+ } catch (e) {
609
+ if (e.code === 'ENOENT') return null
610
+ throw e
611
+ }
612
+ })
613
+ },
614
+ delete: async (_key) => {
615
+ return await within_fiber(fullpath, async () => {
706
616
  var fullpath = await get_fullpath()
707
- if (freed || closed) return
617
+ if (freed) return
618
+
708
619
  try {
709
- var stat = await require('fs').promises.stat(fullpath, { bigint: true })
710
- } catch (e) { return }
711
- if (freed || closed) return
712
-
713
- var server_v = JSON.parse(`[${res.headers.get('current-version')}]`)
714
- if (self.version != null &&
715
- '' + stat.mtimeNs === self.file_mtimeNs_str && (
716
- !server_v.length ||
717
- 1*server_v[0] < self.version
718
- )) await send_file(fullpath)
620
+ await require('fs').promises.unlink(fullpath)
621
+ } catch (e) {
622
+ if (e.code !== 'ENOENT') throw e
623
+ }
719
624
  })
625
+ }
626
+ }
720
627
 
721
- self.signal_file_needs_reading = () => {
722
- within_fiber(url, async () => {
723
- if (freed || closed) return
724
-
725
- var fullpath = await get_fullpath()
726
- if (freed || closed) return
727
-
728
- try {
729
- var stat = await require('fs').promises.stat(fullpath, { bigint: true })
730
- } catch (e) { return }
731
- if (freed || closed) return
628
+ var ac
629
+ function start_sync() {
630
+ if (ac) ac.abort()
631
+ if (freed) return
732
632
 
733
- if ('' + stat.mtimeNs !== self.file_mtimeNs_str) {
734
- self.version = Math.max((self.version || 0) + 1,
735
- Math.round(Number(stat.mtimeNs) / 1000000))
633
+ var closed = false
634
+ ac = new AbortController()
736
635
 
737
- self.file_mtimeNs_str = '' + stat.mtimeNs
738
- self.last_touch = Date.now()
636
+ self.disconnect = async () => {
637
+ if (closed) return
638
+ closed = true
639
+ reconnect_rate_limiter.on_diss(url)
640
+ ac.abort()
641
+ }
739
642
 
740
- await save_meta()
741
- await send_file(fullpath)
742
- }
743
- })
744
- }
745
- self.signal_file_needs_reading()
746
- } catch (e) { return retry(e) }
643
+ braid_blob.sync(url, new URL(url), {
644
+ db,
645
+ signal: ac.signal,
646
+ peer: self.peer,
647
+ headers: {
648
+ 'Content-Type': 'text/plain',
649
+ ...(x => x && { Cookie: x })(config.cookies?.[new URL(url).hostname])
650
+ },
651
+ on_pre_connect: () => reconnect_rate_limiter.get_turn(url),
652
+ on_res: res => {
653
+ if (freed) return
654
+ reconnect_rate_limiter.on_conn(url)
655
+ self.file_read_only = res.headers.get('editable') === 'false'
656
+ console.log(`connected to ${url}${self.file_read_only ? ' (readonly)' : ''}`)
657
+ },
658
+ on_unauthorized: async () => {
659
+ console.log(`access denied: reverting local edits`)
660
+ unsync_url(url)
661
+ sync_url(url)
662
+ },
663
+ on_disconnect: () => reconnect_rate_limiter.on_diss(url)
664
+ })
747
665
  }
748
666
 
667
+ self.reconnect = () => start_sync()
668
+
669
+ start_sync()
749
670
  return self
750
671
  }
751
672
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braidfs",
3
- "version": "0.0.132",
3
+ "version": "0.0.133",
4
4
  "description": "braid technology synchronizing files and webpages",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braidfs",
@@ -8,7 +8,7 @@
8
8
  "dependencies": {
9
9
  "braid-http": "~1.3.85",
10
10
  "braid-text": "~0.2.97",
11
- "braid-blob": "~0.0.30",
11
+ "braid-blob": "~0.0.42",
12
12
  "chokidar": "^4.0.3"
13
13
  },
14
14
  "bin": {