braid-blob 0.0.17 → 0.0.18
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 +23 -39
- package/package.json +2 -2
- package/server-demo.js +3 -1
- package/test/tests.js +37 -0
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var {http_server: braidify
|
|
1
|
+
var {http_server: braidify} = require('braid-http'),
|
|
2
2
|
{url_file_db} = require('url-file-db'),
|
|
3
3
|
fs = require('fs'),
|
|
4
4
|
path = require('path')
|
|
@@ -10,7 +10,8 @@ function create_braid_blob() {
|
|
|
10
10
|
cache: {},
|
|
11
11
|
key_to_subs: {},
|
|
12
12
|
peer: null, // we'll try to load this from a file, if not set by the user
|
|
13
|
-
db: null // url-file-db instance
|
|
13
|
+
db: null, // url-file-db instance for blob storage
|
|
14
|
+
meta_db: null // url-file-db instance for meta storage
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
braid_blob.init = async () => {
|
|
@@ -27,10 +28,11 @@ function create_braid_blob() {
|
|
|
27
28
|
await braid_blob.put(key, body, { skip_write: true })
|
|
28
29
|
})
|
|
29
30
|
|
|
30
|
-
// Create meta
|
|
31
|
-
|
|
31
|
+
// Create url-file-db instance for meta storage (in a subfolder)
|
|
32
|
+
// This will create both meta_folder and the db subfolder with recursive: true
|
|
33
|
+
braid_blob.meta_db = await url_file_db.create(`${braid_blob.meta_folder}/db`)
|
|
32
34
|
|
|
33
|
-
// establish a peer id
|
|
35
|
+
// establish a peer id (stored at root of meta_folder, sibling to db subfolder)
|
|
34
36
|
if (!braid_blob.peer)
|
|
35
37
|
try {
|
|
36
38
|
braid_blob.peer = await fs.promises.readFile(`${braid_blob.meta_folder}/peer.txt`, 'utf8')
|
|
@@ -44,12 +46,11 @@ function create_braid_blob() {
|
|
|
44
46
|
braid_blob.put = async (key, body, options = {}) => {
|
|
45
47
|
await braid_blob.init()
|
|
46
48
|
|
|
47
|
-
// Read the meta
|
|
48
|
-
const metaname = `${braid_blob.meta_folder}/${encode_filename(key)}`
|
|
49
|
+
// Read the meta data from meta_db
|
|
49
50
|
var meta = {}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
var meta_content = await braid_blob.meta_db.read(key)
|
|
52
|
+
if (meta_content)
|
|
53
|
+
meta = JSON.parse(meta_content.toString('utf8'))
|
|
53
54
|
|
|
54
55
|
var their_e =
|
|
55
56
|
!options.version ?
|
|
@@ -69,11 +70,11 @@ function create_braid_blob() {
|
|
|
69
70
|
if (!options.skip_write)
|
|
70
71
|
await braid_blob.db.write(key, body)
|
|
71
72
|
|
|
72
|
-
// Write the meta
|
|
73
|
+
// Write the meta data
|
|
73
74
|
if (options.content_type)
|
|
74
75
|
meta.content_type = options.content_type
|
|
75
76
|
|
|
76
|
-
await
|
|
77
|
+
await braid_blob.meta_db.write(key, JSON.stringify(meta))
|
|
77
78
|
|
|
78
79
|
// Notify all subscriptions of the update
|
|
79
80
|
// (except the peer which made the PUT request itself)
|
|
@@ -93,12 +94,11 @@ function create_braid_blob() {
|
|
|
93
94
|
braid_blob.get = async (key, options = {}) => {
|
|
94
95
|
await braid_blob.init()
|
|
95
96
|
|
|
96
|
-
// Read the meta
|
|
97
|
-
const metaname = `${braid_blob.meta_folder}/${encode_filename(key)}`
|
|
97
|
+
// Read the meta data from meta_db
|
|
98
98
|
var meta = {}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
var meta_content = await braid_blob.meta_db.read(key)
|
|
100
|
+
if (meta_content)
|
|
101
|
+
meta = JSON.parse(meta_content.toString('utf8'))
|
|
102
102
|
if (meta.event == null) return null
|
|
103
103
|
|
|
104
104
|
var result = {
|
|
@@ -171,13 +171,11 @@ function create_braid_blob() {
|
|
|
171
171
|
var body = req.method === 'PUT' && await slurp(req)
|
|
172
172
|
|
|
173
173
|
await within_fiber(options.key, async () => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
// Read the meta file
|
|
174
|
+
// Read the meta data from meta_db
|
|
177
175
|
var meta = {}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
var meta_content = await braid_blob.meta_db.read(options.key)
|
|
177
|
+
if (meta_content)
|
|
178
|
+
meta = JSON.parse(meta_content.toString('utf8'))
|
|
181
179
|
|
|
182
180
|
if (req.method === 'GET') {
|
|
183
181
|
if (!res.hasHeader("editable")) res.setHeader("Editable", "true")
|
|
@@ -234,12 +232,8 @@ function create_braid_blob() {
|
|
|
234
232
|
res.setHeader("Version", version_to_header(meta.event != null ? [meta.event] : []))
|
|
235
233
|
res.end('')
|
|
236
234
|
} else if (req.method === 'DELETE') {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
} catch (e) {}
|
|
240
|
-
try {
|
|
241
|
-
await fs.promises.unlink(metaname)
|
|
242
|
-
} catch (e) {}
|
|
235
|
+
await braid_blob.db.delete(options.key)
|
|
236
|
+
await braid_blob.meta_db.delete(options.key)
|
|
243
237
|
res.statusCode = 204 // No Content
|
|
244
238
|
res.end('')
|
|
245
239
|
}
|
|
@@ -275,16 +269,6 @@ function create_braid_blob() {
|
|
|
275
269
|
return ascii_ify(version.map(v => JSON.stringify(v)).join(', '))
|
|
276
270
|
}
|
|
277
271
|
|
|
278
|
-
function encode_filename(filename) {
|
|
279
|
-
// Swap all "!" and "/" characters
|
|
280
|
-
let swapped = filename.replace(/[!/]/g, (match) => (match === "!" ? "/" : "!"))
|
|
281
|
-
|
|
282
|
-
// Encode the filename using encodeURIComponent()
|
|
283
|
-
let encoded = encodeURIComponent(swapped)
|
|
284
|
-
|
|
285
|
-
return encoded
|
|
286
|
-
}
|
|
287
|
-
|
|
288
272
|
function within_fiber(id, func) {
|
|
289
273
|
if (!within_fiber.chains) within_fiber.chains = {}
|
|
290
274
|
var prev = within_fiber.chains[id] || Promise.resolve()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "braid-blob",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Library for collaborative blobs over http using braid.",
|
|
5
5
|
"author": "Braid Working Group",
|
|
6
6
|
"repository": "braid-org/braid-blob",
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"braid-http": "~1.3.82",
|
|
14
|
-
"url-file-db": "~0.0.
|
|
14
|
+
"url-file-db": "~0.0.8"
|
|
15
15
|
}
|
|
16
16
|
}
|
package/server-demo.js
CHANGED
|
@@ -8,6 +8,8 @@ var braid_blob = require(`${__dirname}/index.js`)
|
|
|
8
8
|
// braid_blob.db_folder = './custom_files_folder'
|
|
9
9
|
// braid_blob.meta_folder = './custom_meta_folder'
|
|
10
10
|
|
|
11
|
+
braid_blob.init()
|
|
12
|
+
|
|
11
13
|
var server = require("http").createServer(async (req, res) => {
|
|
12
14
|
console.log(`${req.method} ${req.url}`)
|
|
13
15
|
|
|
@@ -19,5 +21,5 @@ server.listen(port, () => {
|
|
|
19
21
|
console.log(`files stored in: ${braid_blob.db_folder}`)
|
|
20
22
|
})
|
|
21
23
|
|
|
22
|
-
// curl -X PUT --data-binary @blob.png http://localhost:8888/blob.png
|
|
24
|
+
// curl -X PUT -H "Content-Type: image/png" --data-binary @blob.png http://localhost:8888/blob.png
|
|
23
25
|
// curl http://localhost:8888/blob.png --output new-blob.png
|
package/test/tests.js
CHANGED
|
@@ -688,6 +688,43 @@ runTest(
|
|
|
688
688
|
'false'
|
|
689
689
|
)
|
|
690
690
|
|
|
691
|
+
runTest(
|
|
692
|
+
"test that meta filenames distinguish between 'a' and 'A' on case-insensitive filesystems",
|
|
693
|
+
async () => {
|
|
694
|
+
var suffix = Math.random().toString(36).slice(2)
|
|
695
|
+
var key1 = 'test-' + suffix + '-a'
|
|
696
|
+
var key2 = 'test-' + suffix + '-A'
|
|
697
|
+
|
|
698
|
+
// PUT to lowercase key with version 100
|
|
699
|
+
var r = await braid_fetch(`/${key1}`, {
|
|
700
|
+
method: 'PUT',
|
|
701
|
+
version: ['100'],
|
|
702
|
+
body: 'lowercase content'
|
|
703
|
+
})
|
|
704
|
+
if (!r.ok) throw 'PUT to lowercase key failed: ' + r.status
|
|
705
|
+
|
|
706
|
+
// PUT to uppercase key with version 200
|
|
707
|
+
var r = await braid_fetch(`/${key2}`, {
|
|
708
|
+
method: 'PUT',
|
|
709
|
+
version: ['200'],
|
|
710
|
+
body: 'uppercase content'
|
|
711
|
+
})
|
|
712
|
+
if (!r.ok) throw 'PUT to uppercase key failed: ' + r.status
|
|
713
|
+
|
|
714
|
+
// GET both and verify they have different versions (stored in meta files)
|
|
715
|
+
var r1 = await braid_fetch(`/${key1}`)
|
|
716
|
+
if (!r1.ok) throw 'GET lowercase key failed: ' + r1.status
|
|
717
|
+
var version1 = r1.headers.get('version')
|
|
718
|
+
|
|
719
|
+
var r2 = await braid_fetch(`/${key2}`)
|
|
720
|
+
if (!r2.ok) throw 'GET uppercase key failed: ' + r2.status
|
|
721
|
+
var version2 = r2.headers.get('version')
|
|
722
|
+
|
|
723
|
+
return version1 + '|' + version2
|
|
724
|
+
},
|
|
725
|
+
'"100"|"200"'
|
|
726
|
+
)
|
|
727
|
+
|
|
691
728
|
}
|
|
692
729
|
|
|
693
730
|
// Export for Node.js (CommonJS)
|