braid-blob 0.0.63 → 0.0.65

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 CHANGED
@@ -96,7 +96,7 @@ Subscribe: true
96
96
  Response (keeps connection open, streams updates):
97
97
 
98
98
  ```http
99
- HTTP/1.1 209 Subscription
99
+ HTTP/1.1 209 Multiresponse
100
100
  Subscribe: true
101
101
  Current-Version: "alice-1"
102
102
 
@@ -136,10 +136,10 @@ Response:
136
136
 
137
137
  ```http
138
138
  HTTP/1.1 200 OK
139
- Version: "carol-3"
139
+ Current-Version: "carol-3"
140
140
  ```
141
141
 
142
- If the sent version is older or eclipsed by the server's current version, the returned `Version` will be the server's version (not the one you sent).
142
+ If the sent version is older or eclipsed by the server's current version, the returned `Current-Version` will be the server's version (not the one you sent).
143
143
 
144
144
  The `braid_blob.serve()` method (below) will accept every PUT sent to it, but you can implement access control for any request before passing it to `serve()`, and return e.g. `401 Unauthorized` if you do no want to allow the PUT.
145
145
 
@@ -183,7 +183,7 @@ braid_blob.db_folder = './braid-blobs' // Default: ./braid-blobs
183
183
  Your app becomes a blob server with:
184
184
 
185
185
  ```javascript
186
- braid_blob.serve(req, res, options)
186
+ braid_blob.serve(req, res, params)
187
187
  ```
188
188
 
189
189
  This will synchronize the client issuing the given request and response with its blob on disk.
@@ -191,7 +191,7 @@ This will synchronize the client issuing the given request and response with its
191
191
  Parameters:
192
192
  - `req` - HTTP request object
193
193
  - `res` - HTTP response object
194
- - `options` - Optional configuration object
194
+ - `params` - Optional configuration object
195
195
  - `key` - The blob on disk to sync with (default: `req.url`)
196
196
 
197
197
  ### Sync a remotely served blob to disk
@@ -199,7 +199,7 @@ Parameters:
199
199
  Your app becomes a blob client with:
200
200
 
201
201
  ```javascript
202
- braid_blob.sync(key, url, options)
202
+ braid_blob.sync(key, url, params)
203
203
  ```
204
204
 
205
205
  Synchronizes a remote URL to its blob on disk.
@@ -207,7 +207,7 @@ Synchronizes a remote URL to its blob on disk.
207
207
  Parameters:
208
208
  - `key` - The blob on disk (string)
209
209
  - `url` - Remote URL (URL object)
210
- - `options` - Optional configuration object
210
+ - `params` - Optional configuration object
211
211
  - `signal` - AbortSignal for cancellation (use to stop sync)
212
212
  - `content_type` - Content type for requests
213
213
 
@@ -216,7 +216,7 @@ Parameters:
216
216
  #### Read a local or remote blob
217
217
 
218
218
  ```javascript
219
- braid_blob.get(key, options)
219
+ braid_blob.get(key, params)
220
220
  ```
221
221
 
222
222
  Retrieves a blob from local storage or a remote URL.
@@ -238,7 +238,7 @@ braid_blob.get(
238
238
 
239
239
  Parameters:
240
240
  - `key` - The local blob (if string) or remote URL (if [URL object](https://nodejs.org/api/url.html#class-url)) to read from
241
- - `options` - Optional configuration object
241
+ - `params` - Optional configuration object
242
242
  - `version` - Version ID to check existence (use with `head: true`)
243
243
  - `parent` - Version ID; when subscribing, only receive updates newer than this
244
244
  - `subscribe` - Callback function for real-time updates
@@ -251,7 +251,7 @@ Returns: `{version, body, content_type}` object, or `null` if not found.
251
251
  #### Write a local or remote blob
252
252
 
253
253
  ```javascript
254
- braid_blob.put(key, body, options)
254
+ braid_blob.put(key, body, params)
255
255
  ```
256
256
 
257
257
  Writes a blob to local storage or a remote URL. Any other peers synchronizing with this blob (via `.serve()`, `.sync()`, or `.get(.., {subscribe: ..}`) will be updated.
@@ -259,7 +259,7 @@ Writes a blob to local storage or a remote URL. Any other peers synchronizing w
259
259
  Parameters:
260
260
  - `key` - The local blob (if string) or remote URL (if [URL object](https://nodejs.org/api/url.html#class-url)) to write to
261
261
  - `body` - Buffer or data to store
262
- - `options` - Optional configuration object
262
+ - `params` - Optional configuration object
263
263
  - `version` - Version identifier
264
264
  - `content_type` - Content type of the blob
265
265
  - `signal` - AbortSignal for cancellation
@@ -267,14 +267,14 @@ Parameters:
267
267
  #### Delete a local or remote blob
268
268
 
269
269
  ```javascript
270
- braid_blob.delete(key, options)
270
+ braid_blob.delete(key, params)
271
271
  ```
272
272
 
273
273
  Deletes a blob from local storage or a remote URL.
274
274
 
275
275
  Parameters:
276
276
  - `key` - The local blob (if string) or remote URL (if [URL object](https://nodejs.org/api/url.html#class-url)) to delete
277
- - `options` - Optional configuration object
277
+ - `params` - Optional configuration object
278
278
  - `signal` - AbortSignal for cancellation
279
279
 
280
280
  ## Browser Client API
@@ -300,14 +300,14 @@ A simple browser client is included for subscribing to blob updates.
300
300
  ### Subscribe to remote blob
301
301
 
302
302
  ```javascript
303
- braid_blob_client(url, options)
303
+ braid_blob_client(url, params)
304
304
  ```
305
305
 
306
- Subscribes to a blob endpoint, and calls `options.on_update()` with each update.
306
+ Subscribes to a blob endpoint, and calls `params.on_update()` with each update.
307
307
 
308
308
  Parameters:
309
309
  - `url` - The blob endpoint URL
310
- - `options` - Configuration object
310
+ - `params` - Configuration object
311
311
  - `on_update(blob, content_type, version)` - Callback for updates
312
312
  - `on_delete` - Callback when blob is deleted
313
313
  - `on_error(e)` - Callback for errors
package/client.js CHANGED
@@ -20,8 +20,8 @@
20
20
  // // Update the blob with new data
21
21
  // await blob.update(body, 'text/plain')
22
22
  //
23
- function braid_blob_client(url, options = {}) {
24
- var peer = options.peer || Math.random().toString(36).slice(2)
23
+ function braid_blob_client(url, params = {}) {
24
+ var peer = params.peer || Math.random().toString(36).slice(2)
25
25
  var current_version = null
26
26
 
27
27
  braid_fetch(url, {
@@ -30,24 +30,24 @@ function braid_blob_client(url, options = {}) {
30
30
  parents: () => [current_version],
31
31
  peer,
32
32
  retry: () => true,
33
- signal: options.signal
33
+ signal: params.signal
34
34
  }).then(res => {
35
35
  res.subscribe(async update => {
36
36
  if (update.status == 404) {
37
37
  current_version = null
38
- return options.on_delete?.()
38
+ return params.on_delete?.()
39
39
  }
40
40
 
41
41
  // Only update if version is newer
42
42
  var version = update.version?.[0]
43
43
  if (compare_events(version, current_version) > 0) {
44
44
  current_version = version
45
- options.on_update?.(update.body,
45
+ params.on_update?.(update.body,
46
46
  update.extra_headers?.['content-type'],
47
47
  current_version)
48
48
  }
49
- }, e => options.on_error?.(e))
50
- }).catch(e => options.on_error?.(e))
49
+ }, e => params.on_error?.(e))
50
+ }).catch(e => params.on_error?.(e))
51
51
 
52
52
  return {
53
53
  update: async (body, content_type) => {
@@ -55,7 +55,7 @@ function braid_blob_client(url, options = {}) {
55
55
  increment_seq(get_event_seq(current_version)))
56
56
  current_version = `${peer}-${seq}`
57
57
 
58
- options.on_update?.(body, content_type, current_version)
58
+ params.on_update?.(body, content_type, current_version)
59
59
 
60
60
  await braid_fetch(url, {
61
61
  method: 'PUT',
@@ -26,7 +26,7 @@
26
26
  <h1>Braid-Blob Live Image Demo</h1>
27
27
  <p>This image updates in real-time across all connected clients.</p>
28
28
 
29
- <img live src="/blob.png" alt="Live updating image">
29
+ <img live droppable src="/blob.png" alt="Live updating image">
30
30
 
31
31
  <script src="https://unpkg.com/braid-http@~1.3/braid-http-client.js"></script>
32
32
  <script src="client.js"></script>
package/img-live.js CHANGED
@@ -1,17 +1,17 @@
1
1
  // Braid-Blob Live Images
2
2
  // requires client.js
3
3
 
4
- var live_images = new Map() // img -> ac
4
+ var live_images = new Map() // img -> { ac, client }
5
5
 
6
6
  function sync(img) {
7
7
  var url = img.src
8
8
  if (!url) return
9
- if (live_images.has(img)) return
10
9
 
11
- var ac = new AbortController()
12
- live_images.set(img, ac)
10
+ // Unsync first to handle attribute changes (e.g. droppable added/removed)
11
+ unsync(img)
13
12
 
14
- braid_blob_client(url, {
13
+ var ac = new AbortController()
14
+ var client = braid_blob_client(url, {
15
15
  signal: ac.signal,
16
16
  on_update: (body, content_type) => {
17
17
  var blob = new Blob([body], { type: content_type || 'image/png' })
@@ -21,16 +21,55 @@ function sync(img) {
21
21
  console.error('Live image error for', url, error)
22
22
  }
23
23
  })
24
+ live_images.set(img, { ac, client })
25
+
26
+ if (img.hasAttribute('droppable'))
27
+ make_droppable(img)
24
28
  }
25
29
 
26
30
  function unsync(img) {
27
- var ac = live_images.get(img)
28
- if (ac) {
29
- ac.abort()
31
+ var entry = live_images.get(img)
32
+ if (entry) {
33
+ entry.ac.abort()
30
34
  live_images.delete(img)
31
35
  }
32
36
  }
33
37
 
38
+ function make_droppable(img) {
39
+ img.addEventListener('dragenter', function(e) {
40
+ img.style.outline = '3px dashed #007bff'
41
+ img.style.outlineOffset = '3px'
42
+ })
43
+
44
+ img.addEventListener('dragleave', function(e) {
45
+ img.style.outline = ''
46
+ img.style.outlineOffset = ''
47
+ })
48
+
49
+ img.addEventListener('dragover', function(e) {
50
+ e.preventDefault()
51
+ e.dataTransfer.dropEffect = 'copy'
52
+ })
53
+
54
+ img.addEventListener('drop', function(e) {
55
+ e.preventDefault()
56
+ img.style.outline = ''
57
+ img.style.outlineOffset = ''
58
+
59
+ var file = e.dataTransfer.files[0]
60
+ if (!file || !file.type.startsWith('image/')) return
61
+
62
+ var entry = live_images.get(img)
63
+ if (!entry) return
64
+
65
+ var reader = new FileReader()
66
+ reader.onload = function() {
67
+ entry.client.update(reader.result, file.type)
68
+ }
69
+ reader.readAsArrayBuffer(file)
70
+ })
71
+ }
72
+
34
73
  var observer = new MutationObserver(function(mutations) {
35
74
  mutations.forEach(function(mutation) {
36
75
  mutation.addedNodes.forEach(function(node) {
@@ -47,10 +86,10 @@ var observer = new MutationObserver(function(mutations) {
47
86
  node.querySelectorAll('img[live]').forEach(unsync)
48
87
  }
49
88
  })
50
- if (mutation.type === 'attributes' && mutation.attributeName === 'live' && mutation.target.tagName === 'IMG') {
89
+ if (mutation.type === 'attributes' && mutation.target.tagName === 'IMG') {
51
90
  if (mutation.target.hasAttribute('live'))
52
91
  sync(mutation.target)
53
- else
92
+ else if (mutation.attributeName === 'live')
54
93
  unsync(mutation.target)
55
94
  }
56
95
  })
@@ -66,7 +105,7 @@ function init() {
66
105
  childList: true,
67
106
  subtree: true,
68
107
  attributes: true,
69
- attributeFilter: ['live']
108
+ attributeFilter: ['live', 'droppable']
70
109
  })
71
110
 
72
111
  document.querySelectorAll('img[live]').forEach(sync)
package/index.js CHANGED
@@ -13,9 +13,9 @@ function create_braid_blob() {
13
13
  reconnect_delay_ms: 1000,
14
14
  }
15
15
 
16
- braid_blob.sync = (a, b, options = {}) => {
17
- options = normalize_options(options)
18
- if (!options.peer) options.peer = Math.random().toString(36).slice(2)
16
+ braid_blob.sync = (a, b, params = {}) => {
17
+ params = normalize_params(params)
18
+ if (!params.peer) params.peer = Math.random().toString(36).slice(2)
19
19
 
20
20
  // Support for same-type params removed for now,
21
21
  // since it is unused, unoptimized,
@@ -28,26 +28,26 @@ function create_braid_blob() {
28
28
  let swap = a; a = b; b = swap
29
29
  }
30
30
 
31
- reconnector(options.signal, (_e, count) => {
31
+ reconnector(params.signal, (_e, count) => {
32
32
  var delay = braid_blob.reconnect_delay_ms ?? Math.min(count, 3) * 1000
33
33
  console.log(`disconnected from ${b.href}, retrying in ${delay}ms`)
34
34
  return delay
35
35
  }, async (signal, handle_error) => {
36
36
  if (signal.aborted) return
37
- if (options.on_pre_connect) await options.on_pre_connect()
37
+ if (params.on_pre_connect) await params.on_pre_connect()
38
38
 
39
39
  try {
40
40
  // Check if remote has our current version (simple fork-point check)
41
41
  var server_has_our_version = false
42
42
  var local_version = (await braid_blob.get(a, {
43
- ...options,
43
+ ...params,
44
44
  signal,
45
45
  head: true
46
46
  }))?.version
47
47
  if (signal.aborted) return
48
48
  if (local_version) {
49
49
  var r = await braid_blob.get(b, {
50
- ...options,
50
+ ...params,
51
51
  signal,
52
52
  head: true,
53
53
  dont_retry: true,
@@ -59,14 +59,14 @@ function create_braid_blob() {
59
59
 
60
60
  // Local -> remote
61
61
  await braid_blob.get(a, {
62
- ...options,
62
+ ...params,
63
63
  signal,
64
64
  parents: server_has_our_version ? local_version : null,
65
65
  subscribe: async update => {
66
66
  try {
67
67
  if (update.delete) {
68
68
  var x = await braid_blob.delete(b, {
69
- ...options,
69
+ ...params,
70
70
  signal,
71
71
  dont_retry: true,
72
72
  content_type: update.content_type,
@@ -75,15 +75,15 @@ function create_braid_blob() {
75
75
  if (!x.ok) handle_error(new Error('failed to delete'))
76
76
  } else {
77
77
  var x = await braid_blob.put(b, update.body, {
78
- ...options,
78
+ ...params,
79
79
  signal,
80
80
  dont_retry: true,
81
81
  version: update.version,
82
82
  content_type: update.content_type,
83
83
  })
84
84
  if (signal.aborted) return
85
- if ((x.status === 401 || x.status === 403) && options.on_unauthorized) {
86
- await options.on_unauthorized?.()
85
+ if ((x.status === 401 || x.status === 403) && params.on_unauthorized) {
86
+ await params.on_unauthorized?.()
87
87
  } else if (!x.ok) handle_error(new Error('failed to PUT: ' + x.status))
88
88
  }
89
89
  } catch (e) { handle_error(e) }
@@ -92,39 +92,39 @@ function create_braid_blob() {
92
92
 
93
93
  // Remote -> local
94
94
  var remote_res = await braid_blob.get(b, {
95
- ...options,
95
+ ...params,
96
96
  signal,
97
97
  dont_retry: true,
98
98
  parents: local_version,
99
99
  subscribe: async update => {
100
100
  if (update.delete) await braid_blob.delete(a, {
101
- ...options,
101
+ ...params,
102
102
  signal,
103
103
  content_type: update.content_type,
104
104
  })
105
105
  else await braid_blob.put(a, update.body, {
106
- ...options,
106
+ ...params,
107
107
  signal,
108
108
  version: update.version,
109
109
  content_type: update.content_type,
110
110
  })
111
111
  },
112
112
  on_error: e => {
113
- options.on_disconnect?.()
113
+ params.on_disconnect?.()
114
114
  handle_error(e)
115
115
  }
116
116
  })
117
- options.on_res?.(remote_res)
117
+ params.on_res?.(remote_res)
118
118
  } catch (e) { handle_error(e) }
119
119
  })
120
120
  }
121
121
 
122
- braid_blob.serve = async (req, res, options = {}) => {
122
+ braid_blob.serve = async (req, res, params = {}) => {
123
123
  await braid_blob.init()
124
124
 
125
- if (!options.key) {
125
+ if (!params.key) {
126
126
  var url = new URL(req.url, 'http://localhost')
127
- options.key = url.pathname
127
+ params.key = url.pathname
128
128
  }
129
129
 
130
130
  free_cors(res)
@@ -144,7 +144,7 @@ function create_braid_blob() {
144
144
  res.setHeader("Merge-Type", "aww")
145
145
 
146
146
  try {
147
- var result = await braid_blob.get(options.key, {
147
+ var result = await braid_blob.get(params.key, {
148
148
  peer: req.peer,
149
149
  head: req.method === "HEAD",
150
150
  version: req.version,
@@ -198,15 +198,15 @@ function create_braid_blob() {
198
198
  }
199
199
  } else if (req.method === 'PUT') {
200
200
  // Handle PUT request to update binary files
201
- var event = await braid_blob.put(options.key, body, {
201
+ var event = await braid_blob.put(params.key, body, {
202
202
  version: req.version,
203
203
  content_type: req.headers['content-type'],
204
204
  peer: req.peer
205
205
  })
206
- res.setHeader("Version", version_to_header(event != null ? [event] : []))
206
+ res.setHeader("Current-Version", version_to_header(event != null ? [event] : []))
207
207
  res.end('')
208
208
  } else if (req.method === 'DELETE') {
209
- await braid_blob.delete(options.key, {
209
+ await braid_blob.delete(params.key, {
210
210
  content_type: req.headers['content-type'],
211
211
  peer: req.peer
212
212
  })
@@ -214,44 +214,44 @@ function create_braid_blob() {
214
214
  }
215
215
  }
216
216
 
217
- braid_blob.get = async (key, options = {}) => {
218
- options = normalize_options(options)
217
+ braid_blob.get = async (key, params = {}) => {
218
+ params = normalize_params(params)
219
219
 
220
220
  // Handle URL case - make a remote GET request
221
221
  if (key instanceof URL) {
222
- var params = {
223
- signal: options.signal,
224
- subscribe: options.subscribe,
222
+ var fetch_params = {
223
+ signal: params.signal,
224
+ subscribe: params.subscribe,
225
225
  heartbeats: 120,
226
226
  }
227
- if (!options.dont_retry) {
228
- params.retry = (res) => res.status !== 309 &&
227
+ if (!params.dont_retry) {
228
+ fetch_params.retry = (res) => res.status !== 309 &&
229
229
  res.status !== 404 && res.status !== 406
230
230
  }
231
- if (options.head) params.method = 'HEAD'
231
+ if (params.head) fetch_params.method = 'HEAD'
232
232
  for (var x of ['headers', 'parents', 'version', 'peer'])
233
- if (options[x] != null) params[x] = options[x]
234
- if (options.content_type)
235
- params.headers = { ...params.headers,
236
- 'Accept': options.content_type }
233
+ if (params[x] != null) fetch_params[x] = params[x]
234
+ if (params.content_type)
235
+ fetch_params.headers = { ...fetch_params.headers,
236
+ 'Accept': params.content_type }
237
237
 
238
- var res = await braid_fetch(key.href, params)
238
+ var res = await braid_fetch(key.href, fetch_params)
239
239
 
240
240
  if (!res.ok)
241
- if (options.subscribe) throw new Error('failed to subscribe')
241
+ if (params.subscribe) throw new Error('failed to subscribe')
242
242
  else return null
243
243
 
244
244
  var result = {}
245
245
  if (res.version) result.version = res.version
246
246
 
247
- if (options.head) return result
247
+ if (params.head) return result
248
248
 
249
- if (options.subscribe) {
249
+ if (params.subscribe) {
250
250
  res.subscribe(async update => {
251
251
  if (update.status === 404) update.delete = true
252
252
  update.content_type = update.extra_headers['content-type']
253
- await options.subscribe(update)
254
- }, e => options.on_error?.(e))
253
+ await params.subscribe(update)
254
+ }, e => params.on_error?.(e))
255
255
  return res
256
256
  } else {
257
257
  result.body = await res.arrayBuffer()
@@ -260,103 +260,103 @@ function create_braid_blob() {
260
260
  }
261
261
 
262
262
  await braid_blob.init()
263
- if (options.signal?.aborted) return
263
+ if (params.signal?.aborted) return
264
264
 
265
265
  return await within_fiber(key, async () => {
266
266
  var meta = await get_meta(key)
267
- if (options.signal?.aborted) return
267
+ if (params.signal?.aborted) return
268
268
 
269
- if (!meta.event && !options.subscribe) return null
269
+ if (!meta.event && !params.subscribe) return null
270
270
 
271
271
  var result = {
272
272
  version: meta.event ? [meta.event] : [],
273
273
  content_type: meta.content_type
274
274
  }
275
275
 
276
- if (options.header_cb) await options.header_cb(result)
277
- if (options.signal?.aborted) return
276
+ if (params.header_cb) await params.header_cb(result)
277
+ if (params.signal?.aborted) return
278
278
 
279
279
  // Check if requested version/parents is newer than what we have - if so, we don't have it
280
- if (!options.subscribe) {
281
- if (compare_events(options.version?.[0], meta.event) > 0)
282
- throw new Error('unknown version: ' + options.version)
283
- if (compare_events(options.parents?.[0], meta.event) > 0)
284
- throw new Error('unknown version: ' + options.parents)
280
+ if (!params.subscribe) {
281
+ if (compare_events(params.version?.[0], meta.event) > 0)
282
+ throw new Error('unknown version: ' + params.version)
283
+ if (compare_events(params.parents?.[0], meta.event) > 0)
284
+ throw new Error('unknown version: ' + params.parents)
285
285
  }
286
- if (options.head) return result
286
+ if (params.head) return result
287
287
 
288
- if (options.subscribe) {
288
+ if (params.subscribe) {
289
289
  var subscribe_chain = Promise.resolve()
290
- options.my_subscribe = (x) => subscribe_chain =
290
+ params.my_subscribe = (x) => subscribe_chain =
291
291
  subscribe_chain.then(() =>
292
- !options.signal?.aborted && options.subscribe(x))
292
+ !params.signal?.aborted && params.subscribe(x))
293
293
 
294
294
  // Start a subscription for future updates
295
295
  if (!braid_blob.key_to_subs[key])
296
296
  braid_blob.key_to_subs[key] = new Map()
297
297
 
298
- var peer = options.peer || Math.random().toString(36).slice(2)
298
+ var peer = params.peer || Math.random().toString(36).slice(2)
299
299
  braid_blob.key_to_subs[key].set(peer, {
300
300
  sendUpdate: (update) => {
301
- if (update.delete) options.my_subscribe(update)
302
- else if (compare_events(update.version[0], options.parents?.[0]) > 0)
303
- options.my_subscribe(update)
301
+ if (update.delete) params.my_subscribe(update)
302
+ else if (compare_events(update.version[0], params.parents?.[0]) > 0)
303
+ params.my_subscribe(update)
304
304
  }
305
305
  })
306
306
 
307
- options.signal?.addEventListener('abort', () => {
307
+ params.signal?.addEventListener('abort', () => {
308
308
  braid_blob.key_to_subs[key].delete(peer)
309
309
  if (!braid_blob.key_to_subs[key].size)
310
310
  delete braid_blob.key_to_subs[key]
311
311
  })
312
312
 
313
- if (options.before_send_cb) await options.before_send_cb()
314
- if (options.signal?.aborted) return
313
+ if (params.before_send_cb) await params.before_send_cb()
314
+ if (params.signal?.aborted) return
315
315
 
316
316
  // Send an immediate update if needed
317
- if (compare_events(result.version?.[0], options.parents?.[0]) > 0) {
317
+ if (compare_events(result.version?.[0], params.parents?.[0]) > 0) {
318
318
  result.sent = true
319
- result.body = await (options.db || braid_blob.db).read(key)
320
- options.my_subscribe(result)
319
+ result.body = await (params.db || braid_blob.db).read(key)
320
+ params.my_subscribe(result)
321
321
  }
322
322
  } else {
323
323
  // If not subscribe, send the body now
324
- result.body = await (options.db || braid_blob.db).read(key)
324
+ result.body = await (params.db || braid_blob.db).read(key)
325
325
  }
326
326
 
327
327
  return result
328
328
  })
329
329
  }
330
330
 
331
- braid_blob.put = async (key, body, options = {}) => {
332
- options = normalize_options(options)
331
+ braid_blob.put = async (key, body, params = {}) => {
332
+ params = normalize_params(params)
333
333
 
334
334
  // Handle URL case - make a remote PUT request
335
335
  if (key instanceof URL) {
336
- var params = {
336
+ var fetch_params = {
337
337
  method: 'PUT',
338
- signal: options.signal,
338
+ signal: params.signal,
339
339
  body
340
340
  }
341
- if (!options.dont_retry)
342
- params.retry = () => true
341
+ if (!params.dont_retry)
342
+ fetch_params.retry = () => true
343
343
  for (var x of ['headers', 'version', 'peer'])
344
- if (options[x] != null) params[x] = options[x]
345
- if (options.content_type)
346
- params.headers = { ...params.headers,
347
- 'Content-Type': options.content_type }
344
+ if (params[x] != null) fetch_params[x] = params[x]
345
+ if (params.content_type)
346
+ fetch_params.headers = { ...fetch_params.headers,
347
+ 'Content-Type': params.content_type }
348
348
 
349
- return await braid_fetch(key.href, params)
349
+ return await braid_fetch(key.href, fetch_params)
350
350
  }
351
351
 
352
352
  await braid_blob.init()
353
- if (options.signal?.aborted) return
353
+ if (params.signal?.aborted) return
354
354
 
355
355
  return await within_fiber(key, async () => {
356
356
  var meta = await get_meta(key)
357
- if (options.signal?.aborted) return
357
+ if (params.signal?.aborted) return
358
358
 
359
- var their_e = options.version ? options.version[0] :
359
+ var their_e = params.version ? params.version[0] :
360
360
  // we'll give them a event id in this case
361
361
  `${braid_blob.peer}-${max_seq('' + Date.now(),
362
362
  meta.event ? increment_seq(get_event_seq(meta.event)) : '')}`
@@ -364,15 +364,15 @@ function create_braid_blob() {
364
364
  if (compare_events(their_e, meta.event) > 0) {
365
365
  meta.event = their_e
366
366
 
367
- if (!options.skip_write)
368
- await (options.db || braid_blob.db).write(key, body)
369
- if (options.signal?.aborted) return
367
+ if (!params.skip_write)
368
+ await (params.db || braid_blob.db).write(key, body)
369
+ if (params.signal?.aborted) return
370
370
 
371
- if (options.content_type)
372
- meta.content_type = options.content_type
371
+ if (params.content_type)
372
+ meta.content_type = params.content_type
373
373
 
374
374
  save_meta(key, meta)
375
- if (options.signal?.aborted) return
375
+ if (params.signal?.aborted) return
376
376
 
377
377
  // Notify all subscriptions of the update
378
378
  // (except the peer which made the PUT request itself)
@@ -383,7 +383,7 @@ function create_braid_blob() {
383
383
  }
384
384
  if (braid_blob.key_to_subs[key])
385
385
  for (var [peer, sub] of braid_blob.key_to_subs[key].entries())
386
- if (!options.peer || options.peer !== peer)
386
+ if (!params.peer || params.peer !== peer)
387
387
  await sub.sendUpdate(update)
388
388
  }
389
389
 
@@ -391,35 +391,35 @@ function create_braid_blob() {
391
391
  })
392
392
  }
393
393
 
394
- braid_blob.delete = async (key, options = {}) => {
395
- options = normalize_options(options)
394
+ braid_blob.delete = async (key, params = {}) => {
395
+ params = normalize_params(params)
396
396
 
397
397
  // Handle URL case - make a remote DELETE request
398
398
  if (key instanceof URL) {
399
- var params = {
399
+ var fetch_params = {
400
400
  method: 'DELETE',
401
- signal: options.signal
401
+ signal: params.signal
402
402
  }
403
- if (!options.dont_retry)
404
- params.retry = (res) => res.status !== 309 &&
403
+ if (!params.dont_retry)
404
+ fetch_params.retry = (res) => res.status !== 309 &&
405
405
  res.status !== 404 && res.status !== 406
406
406
  for (var x of ['headers', 'peer'])
407
- if (options[x] != null) params[x] = options[x]
408
- if (options.content_type)
409
- params.headers = { ...params.headers,
410
- 'Accept': options.content_type }
407
+ if (params[x] != null) fetch_params[x] = params[x]
408
+ if (params.content_type)
409
+ fetch_params.headers = { ...fetch_params.headers,
410
+ 'Accept': params.content_type }
411
411
 
412
- return await braid_fetch(key.href, params)
412
+ return await braid_fetch(key.href, fetch_params)
413
413
  }
414
414
 
415
415
  await braid_blob.init()
416
- if (options.signal?.aborted) return
416
+ if (params.signal?.aborted) return
417
417
 
418
418
  return await within_fiber(key, async () => {
419
419
  var meta = await get_meta(key)
420
- if (options.signal?.aborted) return
420
+ if (params.signal?.aborted) return
421
421
 
422
- await (options.db || braid_blob.db).delete(key)
422
+ await (params.db || braid_blob.db).delete(key)
423
423
  await delete_meta(key)
424
424
 
425
425
  // Notify all subscriptions of the delete
@@ -430,7 +430,7 @@ function create_braid_blob() {
430
430
  }
431
431
  if (braid_blob.key_to_subs[key])
432
432
  for (var [peer, sub] of braid_blob.key_to_subs[key].entries())
433
- if (!options.peer || options.peer !== peer)
433
+ if (!params.peer || params.peer !== peer)
434
434
  sub.sendUpdate(update)
435
435
  })
436
436
  }
@@ -728,9 +728,9 @@ function create_braid_blob() {
728
728
  return s
729
729
  }
730
730
 
731
- function normalize_options(options = {}) {
732
- if (!normalize_options.special) {
733
- normalize_options.special = {
731
+ function normalize_params(params = {}) {
732
+ if (!normalize_params.special) {
733
+ normalize_params.special = {
734
734
  version: 'version',
735
735
  parents: 'parents',
736
736
  'content-type': 'content_type',
@@ -740,28 +740,28 @@ function create_braid_blob() {
740
740
  }
741
741
 
742
742
  var normalized = {}
743
- Object.assign(normalized, options)
743
+ Object.assign(normalized, params)
744
744
 
745
745
  // Normalize top-level accept to content_type
746
- if (options.accept) {
747
- normalized.content_type = options.accept
746
+ if (params.accept) {
747
+ normalized.content_type = params.accept
748
748
  delete normalized.accept
749
749
  }
750
750
 
751
- if (options.headers) {
751
+ if (params.headers) {
752
752
  normalized.headers = {}
753
- for (var [k, v] of (options.headers instanceof Headers ?
754
- options.headers.entries() :
755
- Object.entries(options.headers))) {
756
- var s = normalize_options.special[k.toLowerCase()]
753
+ for (var [k, v] of (params.headers instanceof Headers ?
754
+ params.headers.entries() :
755
+ Object.entries(params.headers))) {
756
+ var s = normalize_params.special[k.toLowerCase()]
757
757
  if (s) normalized[s] = v
758
758
  else normalized.headers[k] = v
759
759
  }
760
760
  }
761
761
 
762
762
  // Normalize parent -> parents
763
- if (options.parent)
764
- normalized.parents = options.parent
763
+ if (params.parent)
764
+ normalized.parents = params.parent
765
765
 
766
766
  // Normalize version/parents: allow strings, wrap in array for internal use
767
767
  if (typeof normalized.version === 'string')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-blob",
3
- "version": "0.0.63",
3
+ "version": "0.0.65",
4
4
  "description": "Library for collaborative blobs over http using braid.",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braid-blob",
package/test/tests.js CHANGED
@@ -727,7 +727,7 @@ runTest(
727
727
  })
728
728
  if (!r.ok) throw 'got: ' + r.statusCode
729
729
 
730
- return r.headers.get('version')
730
+ return r.headers.get('current-version')
731
731
  },
732
732
  '"3"'
733
733
  )