braid-text 0.0.4 → 0.0.6
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/README.md +5 -1
- package/index.js +61 -25
- package/package.json +1 -1
- package/server-demo.js +2 -6
package/README.md
CHANGED
|
@@ -105,7 +105,11 @@ server.on("request", (req, res) => {
|
|
|
105
105
|
},
|
|
106
106
|
generate_local_diff_update: (prev_state) => {
|
|
107
107
|
|
|
108
|
-
// Compute diff between prev_state ^ and the current textarea string
|
|
108
|
+
// Compute diff between prev_state ^ and the current textarea string,
|
|
109
|
+
// which might look like [{
|
|
110
|
+
// range: [5:5],
|
|
111
|
+
// content: " World"
|
|
112
|
+
// }] to insert something after a prev_state of "Hello"
|
|
109
113
|
|
|
110
114
|
// Then return the new state (as a string) and the diff (as `patches`)
|
|
111
115
|
return {new_state, patches}
|
package/index.js
CHANGED
|
@@ -167,7 +167,13 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
braid_text.get = async (key, options) => {
|
|
170
|
-
if (!options)
|
|
170
|
+
if (!options) {
|
|
171
|
+
let x = get_resource.cache?.[key]?.doc.get()
|
|
172
|
+
if (x !== undefined) return x
|
|
173
|
+
// if it doesn't exist on disk, don't create it in this case
|
|
174
|
+
if (!(await get_files_for_key(key)).length) return
|
|
175
|
+
return (await get_resource(key)).doc.get()
|
|
176
|
+
}
|
|
171
177
|
|
|
172
178
|
let resource = (typeof key == 'string') ? await get_resource(key) : key
|
|
173
179
|
|
|
@@ -483,6 +489,15 @@ braid_text.put = async (key, options) => {
|
|
|
483
489
|
await resource.db_delta(resource.doc.getPatchSince(v_before))
|
|
484
490
|
}
|
|
485
491
|
|
|
492
|
+
braid_text.list = async () => {
|
|
493
|
+
var pages = new Set()
|
|
494
|
+
for (let x of await require('fs').promises.readdir(braid_text.db_folder)) {
|
|
495
|
+
let m = x.match(/^(.*)\.\d+$/)
|
|
496
|
+
if (m) pages.add(decode_filename(m[1]))
|
|
497
|
+
}
|
|
498
|
+
return [...pages.keys()]
|
|
499
|
+
}
|
|
500
|
+
|
|
486
501
|
async function get_resource(key) {
|
|
487
502
|
let cache = get_resource.cache || (get_resource.cache = {})
|
|
488
503
|
if (cache[key]) return cache[key]
|
|
@@ -494,12 +509,9 @@ async function get_resource(key) {
|
|
|
494
509
|
resource.doc = new Doc("server")
|
|
495
510
|
|
|
496
511
|
let { change, delete_me } = braid_text.db_folder
|
|
497
|
-
? await file_sync(
|
|
498
|
-
braid_text.db_folder,
|
|
499
|
-
encodeURIComponent(key),
|
|
512
|
+
? await file_sync(key,
|
|
500
513
|
(bytes) => resource.doc.mergeBytes(bytes),
|
|
501
|
-
() => resource.doc.toBytes()
|
|
502
|
-
)
|
|
514
|
+
() => resource.doc.toBytes())
|
|
503
515
|
: { change: () => { }, delete_me: () => { } }
|
|
504
516
|
|
|
505
517
|
resource.db_delta = change
|
|
@@ -515,32 +527,30 @@ async function get_resource(key) {
|
|
|
515
527
|
return (cache[key] = resource)
|
|
516
528
|
}
|
|
517
529
|
|
|
518
|
-
async function
|
|
530
|
+
async function get_files_for_key(key) {
|
|
531
|
+
try {
|
|
532
|
+
let re = new RegExp("^" + encode_filename(key).replace(/[^a-zA-Z0-9]/g, "\\$&") + "\\.\\d+$")
|
|
533
|
+
return (await fs.promises.readdir(braid_text.db_folder))
|
|
534
|
+
.filter((a) => re.test(a))
|
|
535
|
+
.map((a) => `${braid_text.db_folder}/${a}`)
|
|
536
|
+
} catch (e) { return [] }
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
async function file_sync(key, process_delta, get_init) {
|
|
519
540
|
let currentNumber = 0
|
|
520
541
|
let currentSize = 0
|
|
521
542
|
let threshold = 0
|
|
522
543
|
|
|
523
544
|
// Ensure the existence of db_folder
|
|
524
545
|
try {
|
|
525
|
-
await fs.promises.access(db_folder);
|
|
546
|
+
await fs.promises.access(braid_text.db_folder);
|
|
526
547
|
} catch (err) {
|
|
527
|
-
|
|
528
|
-
await fs.promises.mkdir(db_folder, { recursive: true });
|
|
529
|
-
} else {
|
|
530
|
-
throw err;
|
|
531
|
-
}
|
|
548
|
+
await fs.promises.mkdir(braid_text.db_folder, { recursive: true });
|
|
532
549
|
}
|
|
533
550
|
|
|
534
551
|
// Read existing files and sort by numbers.
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
return (await fs.promises.readdir(db_folder))
|
|
538
|
-
.filter((a) => re.test(a))
|
|
539
|
-
.sort((a, b) => parseInt(a.match(/\d+$/)[0]) - parseInt(b.match(/\d+$/)[0]))
|
|
540
|
-
.map((a) => `${db_folder}/${a}`)
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
const files = await get_sorted_files()
|
|
552
|
+
const files = (await get_files_for_key(key))
|
|
553
|
+
.sort((a, b) => parseInt(a.match(/\d+$/)[0]) - parseInt(b.match(/\d+$/)[0]))
|
|
544
554
|
|
|
545
555
|
// Try to process files starting from the highest number.
|
|
546
556
|
let done = false
|
|
@@ -581,7 +591,7 @@ async function file_sync(db_folder, filename_base, process_delta, get_init) {
|
|
|
581
591
|
return {
|
|
582
592
|
change: async (bytes) => {
|
|
583
593
|
currentSize += bytes.length + 4 // we account for the extra 4 bytes for uint32
|
|
584
|
-
const filename = `${db_folder}/${
|
|
594
|
+
const filename = `${braid_text.db_folder}/${encode_filename(key)}.${currentNumber}`
|
|
585
595
|
if (currentSize < threshold) {
|
|
586
596
|
console.log(`appending to db..`)
|
|
587
597
|
|
|
@@ -600,7 +610,7 @@ async function file_sync(db_folder, filename_base, process_delta, get_init) {
|
|
|
600
610
|
const buffer = Buffer.allocUnsafe(4)
|
|
601
611
|
buffer.writeUInt32LE(init.length, 0)
|
|
602
612
|
|
|
603
|
-
const newFilename = `${db_folder}/${
|
|
613
|
+
const newFilename = `${braid_text.db_folder}/${encode_filename(key)}.${currentNumber}`
|
|
604
614
|
await fs.promises.writeFile(newFilename, buffer)
|
|
605
615
|
await fs.promises.appendFile(newFilename, init)
|
|
606
616
|
|
|
@@ -619,7 +629,7 @@ async function file_sync(db_folder, filename_base, process_delta, get_init) {
|
|
|
619
629
|
delete_me: async () => {
|
|
620
630
|
await Promise.all(
|
|
621
631
|
(
|
|
622
|
-
await
|
|
632
|
+
await get_files_for_key(key)
|
|
623
633
|
).map((file) => {
|
|
624
634
|
return new Promise((resolve, reject) => {
|
|
625
635
|
fs.unlink(file, (err) => {
|
|
@@ -1260,4 +1270,30 @@ function codePoints_to_index(str, codePoints) {
|
|
|
1260
1270
|
return i
|
|
1261
1271
|
}
|
|
1262
1272
|
|
|
1273
|
+
function encode_filename(filename) {
|
|
1274
|
+
// Replace all '!' with '%21'
|
|
1275
|
+
let encoded = filename.replace(/!/g, '%21');
|
|
1276
|
+
|
|
1277
|
+
// Encode the filename using encodeURIComponent()
|
|
1278
|
+
encoded = encodeURIComponent(encoded);
|
|
1279
|
+
|
|
1280
|
+
// Replace all '%2F' (for '/') with '!'
|
|
1281
|
+
encoded = encoded.replace(/%2F/g, '!');
|
|
1282
|
+
|
|
1283
|
+
return encoded;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
function decode_filename(encodedFilename) {
|
|
1287
|
+
// Replace all '!' with '%2F'
|
|
1288
|
+
let decoded = encodedFilename.replace(/!/g, '%2F');
|
|
1289
|
+
|
|
1290
|
+
// Decode the filename using decodeURIComponent()
|
|
1291
|
+
decoded = decodeURIComponent(decoded);
|
|
1292
|
+
|
|
1293
|
+
// Replace all '%21' with '!'
|
|
1294
|
+
decoded = decoded.replace(/%21/g, '!');
|
|
1295
|
+
|
|
1296
|
+
return decoded;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1263
1299
|
module.exports = braid_text
|
package/package.json
CHANGED
package/server-demo.js
CHANGED
|
@@ -27,11 +27,7 @@ var server = require("http").createServer(async (req, res) => {
|
|
|
27
27
|
// which displays all the currently used keys
|
|
28
28
|
//
|
|
29
29
|
// if (req.url === '/pages') {
|
|
30
|
-
// var pages =
|
|
31
|
-
// for (let x of await require('fs').promises.readdir(db_folder)) {
|
|
32
|
-
// let m = x.match(/^(.*)\.\d+$/)
|
|
33
|
-
// if (m) pages.add(decodeURIComponent(m[1]))
|
|
34
|
-
// }
|
|
30
|
+
// var pages = await braid_text.list()
|
|
35
31
|
// res.writeHead(200, {
|
|
36
32
|
// "Content-Type": "application/json",
|
|
37
33
|
// "Access-Control-Allow-Origin": "*",
|
|
@@ -39,7 +35,7 @@ var server = require("http").createServer(async (req, res) => {
|
|
|
39
35
|
// "Access-Control-Allow-Headers": "*",
|
|
40
36
|
// "Access-Control-Expose-Headers": "*"
|
|
41
37
|
// })
|
|
42
|
-
// res.end(JSON.stringify(
|
|
38
|
+
// res.end(JSON.stringify(pages))
|
|
43
39
|
// return
|
|
44
40
|
// }
|
|
45
41
|
|