braid-http 1.1.1 → 1.2.0

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.
@@ -189,18 +189,32 @@ async function braid_fetch (url, params = {}) {
189
189
  if (params.patches.length === 1) {
190
190
  let patch = params.patches[0]
191
191
  params.headers.set('Content-Range', `${patch.unit} ${patch.range}`)
192
- params.headers.set('Content-Length', `${(new TextEncoder().encode(patch.content)).length}`)
192
+
193
+ if (typeof patch.content === 'string')
194
+ patch.content = new TextEncoder().encode(patch.content)
195
+
196
+ params.headers.set('Content-Length', `${patch.content.length}`)
193
197
  params.body = patch.content
194
198
  }
195
199
 
196
200
  // Multiple patches get sent within a Patches: N block
197
201
  else {
198
202
  params.headers.set('Patches', params.patches.length)
199
- params.body = (params.patches).map(patch => {
200
- var length = `content-length: ${(new TextEncoder().encode(patch.content)).length}`
203
+ let bufs = []
204
+ let te = new TextEncoder()
205
+ for (let patch of params.patches) {
206
+ if (bufs.length) bufs.push(te.encode(`\r\n`))
207
+
208
+ if (typeof patch.content === 'string')
209
+ patch.content = te.encode(patch.content)
210
+
211
+ var length = `content-length: ${patch.content.length}`
201
212
  var range = `content-range: ${patch.unit} ${patch.range}`
202
- return `${length}\r\n${range}\r\n\r\n${patch.content}\r\n`
203
- }).join('\r\n')
213
+ bufs.push(te.encode(`${length}\r\n${range}\r\n\r\n`))
214
+ bufs.push(patch.content)
215
+ bufs.push(te.encode(`\r\n`))
216
+ }
217
+ params.body = new Blob(bufs)
204
218
  }
205
219
  }
206
220
 
@@ -306,10 +320,13 @@ async function braid_fetch (url, params = {}) {
306
320
  // Each time something happens, we'll either get a new
307
321
  // version back, or an error.
308
322
  (result, err) => {
309
- if (!err)
323
+ if (!err) {
324
+ // check whether we aborted
325
+ if (original_signal?.aborted) throw new DOMException('already aborted', 'AbortError')
326
+
310
327
  // Yay! We got a new version! Tell the callback!
311
328
  cb(result)
312
- else
329
+ } else
313
330
  // This error handling code runs if the connection
314
331
  // closes, or if there is unparseable stuff in the
315
332
  // streamed response.
@@ -486,7 +503,18 @@ var subscription_parser = (cb) => ({
486
503
  }
487
504
  })
488
505
 
489
- this.cb(update)
506
+ for (let p of update.patches ?? []) {
507
+ Object.defineProperty(p, 'content_text', {
508
+ get: () => new TextDecoder('utf-8').decode(p.content)
509
+ })
510
+ }
511
+
512
+ try {
513
+ this.cb(update)
514
+ } catch (e) {
515
+ this.cb(null, e)
516
+ return
517
+ }
490
518
 
491
519
  // Reset the parser for the next version!
492
520
  this.state = {input: this.state.input}
@@ -629,7 +657,7 @@ function parse_body (state) {
629
657
  state.patches = [{
630
658
  unit: match.unit,
631
659
  range: match.range,
632
- content: (new TextDecoder('utf-8')).decode(new Uint8Array(state.input.slice(0, content_length))),
660
+ content: new Uint8Array(state.input.slice(0, content_length)),
633
661
 
634
662
  // Question: Perhaps we should include headers here, like we do for
635
663
  // the Patches: N headers below?
@@ -715,7 +743,7 @@ function parse_body (state) {
715
743
 
716
744
  last_patch.unit = match.unit
717
745
  last_patch.range = match.range
718
- last_patch.content = (new TextDecoder('utf-8')).decode(new Uint8Array(state.input.slice(0, content_length)))
746
+ last_patch.content = new Uint8Array(state.input.slice(0, content_length))
719
747
  last_patch.extra_headers = extra_headers(last_patch.headers)
720
748
  delete last_patch.headers // We only keep the extra headers ^^
721
749
 
@@ -66,10 +66,14 @@ ${patch.content}`
66
66
  // Deprecated method for legacy support
67
67
  function parse_patches (req, cb) {
68
68
  parse_update(req, update => {
69
- if (typeof update.body === 'string')
69
+ if (update.body != null) {
70
70
  // Return body as an "everything" patch
71
- cb([{unit: 'everything', range: '', content: update.body}])
72
- else
71
+ let patch = {unit: 'everything', range: '', content: update.body}
72
+ Object.defineProperty(patch, 'content_text', {
73
+ get: () => new TextDecoder('utf-8').decode(patch.content)
74
+ })
75
+ cb([patch])
76
+ } else
73
77
  cb(update.patches)
74
78
  })
75
79
  }
@@ -80,16 +84,20 @@ function parse_update (req, cb) {
80
84
  var num_patches = req.headers.patches
81
85
 
82
86
  if (!num_patches && !req.headers['content-range']) {
83
- var body = ''
84
- req.on('data', chunk => {body += chunk.toString()})
87
+ var buffer = []
88
+ req.on('data', chunk => buffer.push(chunk))
85
89
  req.on('end', () => {
86
- cb({ body, patches: undefined })
90
+ let body = new Uint8Array(Buffer.concat(buffer))
91
+ let update = { body, patches: undefined }
92
+ Object.defineProperty(update, 'body_text', {
93
+ get: () => new TextDecoder('utf-8').decode(update.body)
94
+ })
95
+ cb(update)
87
96
  })
88
97
  }
89
98
 
90
99
  // Parse a single patch, lacking Patches: N
91
100
  else if (num_patches === undefined && req.headers['content-range']) {
92
-
93
101
  // We only support range patches right now, so there must be a
94
102
  // Content-Range header.
95
103
  assert(req.headers['content-range'], 'No patches to parse: need `Patches: N` or `Content-Range:` header in ' + JSON.stringify(req.headers))
@@ -104,8 +112,11 @@ function parse_update (req, cb) {
104
112
  req.on('data', chunk => buffer.push(chunk))
105
113
  // Then return it
106
114
  req.on('end', () => {
107
- patches = [{unit, range, content: Buffer.concat(buffer).toString('utf8')}]
108
- cb({ patches, body: undefined })
115
+ let patch = {unit, range, content: new Uint8Array(Buffer.concat(buffer))}
116
+ Object.defineProperty(patch, 'content_text', {
117
+ get: () => new TextDecoder('utf-8').decode(patch.content)
118
+ })
119
+ cb({ patches: [patch], body: undefined })
109
120
  })
110
121
  }
111
122
 
@@ -136,7 +147,7 @@ function parse_update (req, cb) {
136
147
  if (!('content-length' in headers)) {
137
148
  // Print a nice error if it's missing
138
149
  console.error('No content-length in', JSON.stringify(headers),
139
- 'from', {buffer})
150
+ 'from', new TextDecoder().decode(new Uint8Array(buffer)), {buffer})
140
151
  process.exit(1)
141
152
  }
142
153
 
@@ -150,10 +161,14 @@ function parse_update (req, cb) {
150
161
 
151
162
  // Content-range is of the form '<unit> <range>' e.g. 'json .index'
152
163
  var [unit, range] = parse_content_range(headers['content-range'])
153
- var patch_content = new TextDecoder('utf-8').decode(new Uint8Array(h.remaining_bytes.slice(0, body_length)))
164
+ var patch_content = new Uint8Array(h.remaining_bytes.slice(0, body_length))
154
165
 
155
166
  // We've got our patch!
156
- patches.push({unit, range, content: patch_content})
167
+ let patch = {unit, range, content: patch_content}
168
+ Object.defineProperty(patch, 'content_text', {
169
+ get: () => new TextDecoder('utf-8').decode(patch.content)
170
+ })
171
+ patches.push(patch)
157
172
 
158
173
  buffer = h.remaining_bytes.slice(body_length)
159
174
  }
@@ -215,7 +230,7 @@ function braidify (req, res, next) {
215
230
  (done, err) => parse_patches(
216
231
  req,
217
232
  (patches) => done(patches.map(
218
- p => ({...p, content: JSON.parse(p.content)})
233
+ p => ({...p, content: JSON.parse(p.content_text)})
219
234
  ))
220
235
  )
221
236
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-http",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "An implementation of Braid-HTTP for Node.js and Browsers",
5
5
  "scripts": {
6
6
  "test": "node test/server.js"