braid-text 0.2.34 → 0.2.36
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 +77 -58
- package/package.json +1 -1
- package/test/test.html +196 -11
package/index.js
CHANGED
|
@@ -72,6 +72,10 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
72
72
|
return my_end(200)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
var get_current_version = () => ascii_ify(
|
|
76
|
+
resource.doc.getRemoteVersion().map(x => x.join("-")).sort()
|
|
77
|
+
.map(x => JSON.stringify(x)).join(", "))
|
|
78
|
+
|
|
75
79
|
if (req.method == "GET" || req.method == "HEAD") {
|
|
76
80
|
if (!req.subscribe) {
|
|
77
81
|
res.setHeader("Accept-Subscribe", "true")
|
|
@@ -88,20 +92,29 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
88
92
|
|
|
89
93
|
let x = null
|
|
90
94
|
try {
|
|
91
|
-
x = await braid_text.get(resource, {
|
|
95
|
+
x = await braid_text.get(resource, {
|
|
96
|
+
version: req.version,
|
|
97
|
+
parents: req.parents,
|
|
98
|
+
transfer_encoding: req.headers['accept-transfer-encoding']
|
|
99
|
+
})
|
|
92
100
|
} catch (e) {
|
|
93
101
|
return my_end(500, "The server failed to get something. The error generated was: " + e)
|
|
94
102
|
}
|
|
95
103
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
if (req.headers['accept-transfer-encoding'] === 'dt') {
|
|
105
|
+
res.setHeader("Current-Version", get_current_version())
|
|
106
|
+
res.setHeader("X-Transfer-Encoding", 'dt')
|
|
107
|
+
res.setHeader("Content-Length", x.body.length)
|
|
108
|
+
return my_end(209, req.method === "HEAD" ? null : x.body, 'Multiresponse')
|
|
109
|
+
} else {
|
|
110
|
+
if (req.version || req.parents)
|
|
111
|
+
res.setHeader("Current-Version", get_current_version())
|
|
112
|
+
res.setHeader("Version", ascii_ify(x.version.map((x) => JSON.stringify(x)).join(", ")))
|
|
113
|
+
var buffer = Buffer.from(x.body, "utf8")
|
|
114
|
+
res.setHeader("Repr-Digest", `sha-256=:${require('crypto').createHash('sha256').update(buffer).digest('base64')}:`)
|
|
115
|
+
res.setHeader("Content-Length", buffer.length)
|
|
116
|
+
return my_end(200, req.method === "HEAD" ? null : buffer)
|
|
117
|
+
}
|
|
105
118
|
} else {
|
|
106
119
|
if (!res.hasHeader("editable")) res.setHeader("Editable", "true")
|
|
107
120
|
res.setHeader("Merge-Type", merge_type)
|
|
@@ -112,7 +125,6 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
112
125
|
version: req.version,
|
|
113
126
|
parents: req.parents,
|
|
114
127
|
merge_type,
|
|
115
|
-
transfer_encoding: req.headers['accept-transfer-encoding'],
|
|
116
128
|
subscribe: x => res.sendVersion(x),
|
|
117
129
|
write: (x) => res.write(x)
|
|
118
130
|
}
|
|
@@ -171,7 +183,7 @@ braid_text.serve = async (req, res, options = {}) => {
|
|
|
171
183
|
|
|
172
184
|
await braid_text.put(resource, { peer, version: req.version, parents: req.parents, patches, body, merge_type })
|
|
173
185
|
|
|
174
|
-
res.setHeader("Version",
|
|
186
|
+
res.setHeader("Version", get_current_version())
|
|
175
187
|
|
|
176
188
|
options.put_cb(options.key, resource.val)
|
|
177
189
|
} catch (e) {
|
|
@@ -213,12 +225,38 @@ braid_text.get = async (key, options) => {
|
|
|
213
225
|
let resource = (typeof key == 'string') ? await get_resource(key) : key
|
|
214
226
|
|
|
215
227
|
if (!options.subscribe) {
|
|
216
|
-
|
|
217
|
-
|
|
228
|
+
var version = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
|
|
229
|
+
|
|
230
|
+
if (options.transfer_encoding === 'dt') {
|
|
231
|
+
// optimization: if requesting current version
|
|
232
|
+
// pretend as if they didn't set a version,
|
|
233
|
+
// and let it be handled as the default
|
|
234
|
+
var op_v = options.version
|
|
235
|
+
if (op_v && v_eq(op_v, version)) op_v = null
|
|
236
|
+
|
|
237
|
+
var bytes = null
|
|
238
|
+
if (op_v || options.parents) {
|
|
239
|
+
if (op_v) {
|
|
240
|
+
var doc = dt_get(resource.doc, op_v)
|
|
241
|
+
bytes = doc.toBytes()
|
|
242
|
+
} else {
|
|
243
|
+
bytes = resource.doc.toBytes()
|
|
244
|
+
var doc = Doc.fromBytes(bytes)
|
|
245
|
+
}
|
|
246
|
+
if (options.parents) {
|
|
247
|
+
bytes = doc.getPatchSince(
|
|
248
|
+
dt_get_local_version(bytes, options.parents))
|
|
249
|
+
}
|
|
250
|
+
doc.free()
|
|
251
|
+
} else bytes = resource.doc.toBytes()
|
|
252
|
+
return { body: bytes }
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return options.version || options.parents ? {
|
|
218
256
|
version: options.version || options.parents,
|
|
219
257
|
body: dt_get_string(resource.doc, options.version || options.parents)
|
|
220
258
|
} : {
|
|
221
|
-
version
|
|
259
|
+
version,
|
|
222
260
|
body: resource.doc.get()
|
|
223
261
|
}
|
|
224
262
|
} else {
|
|
@@ -251,52 +289,33 @@ braid_text.get = async (key, options) => {
|
|
|
251
289
|
resource.doc = defrag_dt(resource.doc)
|
|
252
290
|
}
|
|
253
291
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
var bytes = resource.doc.toBytes()
|
|
262
|
-
if (!options.parents && !options.version) o.body = bytes
|
|
263
|
-
else {
|
|
264
|
-
var doc = Doc.fromBytes(bytes)
|
|
265
|
-
o.body = doc.getPatchSince(
|
|
266
|
-
dt_get_local_version(bytes,
|
|
267
|
-
options.parents || options.version))
|
|
268
|
-
doc.free()
|
|
269
|
-
}
|
|
270
|
-
options.subscribe(o)
|
|
271
|
-
} else {
|
|
272
|
-
var updates = null
|
|
273
|
-
if (!options.parents && !options.version) {
|
|
274
|
-
options.subscribe({
|
|
275
|
-
version: [],
|
|
276
|
-
parents: [],
|
|
277
|
-
body: "",
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
updates = dt_get_patches(resource.doc)
|
|
281
|
-
} else {
|
|
282
|
-
// Then start the subscription from the parents in options
|
|
283
|
-
updates = dt_get_patches(resource.doc, options.parents || options.version)
|
|
284
|
-
}
|
|
292
|
+
var updates = null
|
|
293
|
+
if (!options.parents && !options.version) {
|
|
294
|
+
options.subscribe({
|
|
295
|
+
version: [],
|
|
296
|
+
parents: [],
|
|
297
|
+
body: "",
|
|
298
|
+
})
|
|
285
299
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
patches: [{ unit: u.unit, range: u.range, content: u.content }],
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
// Output at least *some* data, or else chrome gets confused and
|
|
294
|
-
// thinks the connection failed. This isn't strictly necessary,
|
|
295
|
-
// but it makes fewer scary errors get printed out in the JS
|
|
296
|
-
// console.
|
|
297
|
-
if (updates.length === 0) options.write?.("\r\n")
|
|
300
|
+
updates = dt_get_patches(resource.doc)
|
|
301
|
+
} else {
|
|
302
|
+
// Then start the subscription from the parents in options
|
|
303
|
+
updates = dt_get_patches(resource.doc, options.parents || options.version)
|
|
298
304
|
}
|
|
299
305
|
|
|
306
|
+
for (let u of updates)
|
|
307
|
+
options.subscribe({
|
|
308
|
+
version: [u.version],
|
|
309
|
+
parents: u.parents,
|
|
310
|
+
patches: [{ unit: u.unit, range: u.range, content: u.content }],
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
// Output at least *some* data, or else chrome gets confused and
|
|
314
|
+
// thinks the connection failed. This isn't strictly necessary,
|
|
315
|
+
// but it makes fewer scary errors get printed out in the JS
|
|
316
|
+
// console.
|
|
317
|
+
if (updates.length === 0) options.write?.("\r\n")
|
|
318
|
+
|
|
300
319
|
resource.clients.add(options)
|
|
301
320
|
}
|
|
302
321
|
}
|
package/package.json
CHANGED
package/test/test.html
CHANGED
|
@@ -69,7 +69,7 @@ async function runTest(testName, testFunction, expectedResult) {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
runTest(
|
|
72
|
-
"test transfer-encoding dt",
|
|
72
|
+
"test transfer-encoding dt (with parents)",
|
|
73
73
|
async () => {
|
|
74
74
|
await dt_p
|
|
75
75
|
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
@@ -85,25 +85,210 @@ runTest(
|
|
|
85
85
|
if (!r.ok) throw 'got: ' + r.statusCode
|
|
86
86
|
|
|
87
87
|
let r2 = await braid_fetch(`/${key}`, {
|
|
88
|
-
|
|
89
|
-
subscribe: true,
|
|
88
|
+
parents: ['hi-0'],
|
|
90
89
|
headers: {
|
|
91
|
-
'Merge-Type': 'dt',
|
|
92
90
|
'Accept-Transfer-Encoding': 'dt'
|
|
93
91
|
}
|
|
94
92
|
})
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
|
|
94
|
+
doc.mergeBytes([...new Uint8Array(await r2.arrayBuffer())])
|
|
95
|
+
var text = doc.get()
|
|
96
|
+
doc.free()
|
|
97
|
+
|
|
98
|
+
return r2.headers.get('current-version') + ' ' + r2.headers.get('x-transfer-encoding') + ' ' + text + ' ' + r2.statusText
|
|
99
|
+
},
|
|
100
|
+
'"hi-1" dt xy Multiresponse'
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
runTest(
|
|
104
|
+
"test transfer-encoding dt",
|
|
105
|
+
async () => {
|
|
106
|
+
await dt_p
|
|
107
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
108
|
+
|
|
109
|
+
let r = await braid_fetch(`/${key}`, {
|
|
110
|
+
method: 'PUT',
|
|
111
|
+
version: ['hi-1'],
|
|
112
|
+
parents: [],
|
|
113
|
+
body: 'xy'
|
|
114
|
+
})
|
|
115
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
116
|
+
|
|
117
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
118
|
+
headers: {
|
|
119
|
+
'Accept-Transfer-Encoding': 'dt'
|
|
120
|
+
}
|
|
102
121
|
})
|
|
122
|
+
|
|
123
|
+
var doc = new Doc('yo')
|
|
124
|
+
doc.mergeBytes([...new Uint8Array(await r2.arrayBuffer())])
|
|
125
|
+
var text = doc.get()
|
|
126
|
+
doc.free()
|
|
127
|
+
|
|
128
|
+
return r2.headers.get('current-version') + ' ' + r2.headers.get('x-transfer-encoding') + ' ' + text
|
|
103
129
|
},
|
|
104
130
|
'"hi-1" dt xy'
|
|
105
131
|
)
|
|
106
132
|
|
|
133
|
+
runTest(
|
|
134
|
+
"test GETing old version explicitly with transfer-encoding dt",
|
|
135
|
+
async () => {
|
|
136
|
+
await dt_p
|
|
137
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
138
|
+
|
|
139
|
+
let r = await braid_fetch(`/${key}`, {
|
|
140
|
+
method: 'PUT',
|
|
141
|
+
version: ['hi∑-1'],
|
|
142
|
+
parents: [],
|
|
143
|
+
body: 'xy'
|
|
144
|
+
})
|
|
145
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
146
|
+
|
|
147
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
148
|
+
version: ['hi∑-0'],
|
|
149
|
+
headers: {
|
|
150
|
+
'Accept-Transfer-Encoding': 'dt'
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
var doc = new Doc('yo')
|
|
155
|
+
doc.mergeBytes([...new Uint8Array(await r2.arrayBuffer())])
|
|
156
|
+
var text = doc.get()
|
|
157
|
+
doc.free()
|
|
158
|
+
|
|
159
|
+
return r2.headers.get('current-version') + ' ' + text + ' ' + JSON.parse(r2.headers.get('current-version'))
|
|
160
|
+
},
|
|
161
|
+
'"hi\\u2211-1" x hi∑-1'
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
runTest(
|
|
165
|
+
"test GETing current version explicitly with transfer-encoding dt",
|
|
166
|
+
async () => {
|
|
167
|
+
await dt_p
|
|
168
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
169
|
+
|
|
170
|
+
let r = await braid_fetch(`/${key}`, {
|
|
171
|
+
method: 'PUT',
|
|
172
|
+
version: ['hi∑-1'],
|
|
173
|
+
parents: [],
|
|
174
|
+
body: 'xy'
|
|
175
|
+
})
|
|
176
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
177
|
+
|
|
178
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
179
|
+
version: ['hi∑-1'],
|
|
180
|
+
headers: {
|
|
181
|
+
'Accept-Transfer-Encoding': 'dt'
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
var doc = new Doc('yo')
|
|
186
|
+
doc.mergeBytes([...new Uint8Array(await r2.arrayBuffer())])
|
|
187
|
+
var text = doc.get()
|
|
188
|
+
doc.free()
|
|
189
|
+
|
|
190
|
+
return r2.headers.get('current-version') + ' ' + text + ' ' + JSON.parse(r2.headers.get('current-version'))
|
|
191
|
+
},
|
|
192
|
+
'"hi\\u2211-1" xy hi∑-1'
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
runTest(
|
|
196
|
+
"test for Current-Version when GETing old version",
|
|
197
|
+
async () => {
|
|
198
|
+
await dt_p
|
|
199
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
200
|
+
|
|
201
|
+
let r = await braid_fetch(`/${key}`, {
|
|
202
|
+
method: 'PUT',
|
|
203
|
+
version: ['hi∑-1'],
|
|
204
|
+
parents: [],
|
|
205
|
+
body: 'xy'
|
|
206
|
+
})
|
|
207
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
208
|
+
|
|
209
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
210
|
+
version: ['hi∑-0']
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
var text = await r2.text()
|
|
214
|
+
|
|
215
|
+
return r2.headers.get('current-version') + ' ' + r2.headers.get('version') + ' ' + text + ' ' + JSON.parse(r2.headers.get('current-version'))
|
|
216
|
+
},
|
|
217
|
+
'"hi\\u2211-1" "hi\\u2211-0" x hi∑-1'
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
runTest(
|
|
221
|
+
"test HEAD for GET without subscribe",
|
|
222
|
+
async () => {
|
|
223
|
+
await dt_p
|
|
224
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
225
|
+
|
|
226
|
+
let r = await braid_fetch(`/${key}`, {
|
|
227
|
+
method: 'PUT',
|
|
228
|
+
version: ['hi∑-1'],
|
|
229
|
+
parents: [],
|
|
230
|
+
body: 'xy'
|
|
231
|
+
})
|
|
232
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
233
|
+
|
|
234
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
235
|
+
method: 'HEAD'
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
var text = await r2.text()
|
|
239
|
+
|
|
240
|
+
return r2.headers.get('version') + ' ' + JSON.parse(r2.headers.get('version')) + ` text:[${text}]`
|
|
241
|
+
},
|
|
242
|
+
'"hi\\u2211-1" hi∑-1 text:[]'
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
runTest(
|
|
246
|
+
"test HEAD for GET without subscribe (with transfer-encoding)",
|
|
247
|
+
async () => {
|
|
248
|
+
await dt_p
|
|
249
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
250
|
+
|
|
251
|
+
let r = await braid_fetch(`/${key}`, {
|
|
252
|
+
method: 'PUT',
|
|
253
|
+
version: ['hi∑-1'],
|
|
254
|
+
parents: [],
|
|
255
|
+
body: 'xy'
|
|
256
|
+
})
|
|
257
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
258
|
+
|
|
259
|
+
let r2 = await braid_fetch(`/${key}`, {
|
|
260
|
+
method: 'HEAD',
|
|
261
|
+
headers: {
|
|
262
|
+
'accept-transfer-encoding': 'dt'
|
|
263
|
+
}
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
var buf = await r2.arrayBuffer()
|
|
267
|
+
|
|
268
|
+
return r2.headers.get('current-version') + ' ' + JSON.parse(r2.headers.get('current-version')) + ` buf.byteLength:${buf.byteLength}`
|
|
269
|
+
},
|
|
270
|
+
'"hi\\u2211-1" hi∑-1 buf.byteLength:0'
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
runTest(
|
|
274
|
+
"test Version we get from PUTing",
|
|
275
|
+
async () => {
|
|
276
|
+
await dt_p
|
|
277
|
+
let key = 'test-' + Math.random().toString(36).slice(2)
|
|
278
|
+
|
|
279
|
+
let r = await braid_fetch(`/${key}`, {
|
|
280
|
+
method: 'PUT',
|
|
281
|
+
version: ['hi∑-1'],
|
|
282
|
+
parents: [],
|
|
283
|
+
body: 'xy'
|
|
284
|
+
})
|
|
285
|
+
if (!r.ok) throw 'got: ' + r.statusCode
|
|
286
|
+
|
|
287
|
+
return r.headers.get('version')
|
|
288
|
+
},
|
|
289
|
+
'"hi\\u2211-1"'
|
|
290
|
+
)
|
|
291
|
+
|
|
107
292
|
runTest(
|
|
108
293
|
"test error code when missing parents",
|
|
109
294
|
async () => {
|