@mblaney/holster 0.2.0 → 1.0.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.
- package/build/holster.js +3 -3
- package/build/holster.js.map +3 -3
- package/examples/user.js +3 -3
- package/package.json +1 -1
- package/src/get.js +17 -10
- package/src/ham.js +18 -20
- package/src/holster.js +246 -121
- package/src/index.js +0 -1
- package/src/sea-utils.js +1 -1
- package/src/sea.js +16 -4
- package/src/store.js +1 -1
- package/src/user.js +21 -22
- package/src/utils.js +13 -6
- package/src/wire.js +21 -15
- package/test/holster.get.test.js +32 -2
- package/test/holster.on.test.js +46 -5
- package/test/holster.put.test.js +19 -2
- package/test/holster.secure.test.js +1 -9
- package/test/holster.user.get.test.js +27 -4
- package/test/holster.user.lex.test.js +2 -2
- package/test/holster.user.on.test.js +58 -4
- package/test/holster.user.put.test.js +129 -49
- package/test/wire.test.js +7 -8
package/src/holster.js
CHANGED
|
@@ -35,80 +35,94 @@ const Holster = opt => {
|
|
|
35
35
|
const keys = []
|
|
36
36
|
for (const [key, value] of Object.entries(data)) {
|
|
37
37
|
if (key === "_") {
|
|
38
|
-
return "error underscore cannot be used as
|
|
38
|
+
return "error underscore cannot be used as a property name"
|
|
39
39
|
}
|
|
40
40
|
if (utils.obj.is(value) || ok(value)) {
|
|
41
41
|
keys.push(key)
|
|
42
42
|
continue
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
if (typeof value === "undefined") {
|
|
45
|
+
return `error undefined ${key} cannot be converted to a graph`
|
|
46
|
+
}
|
|
47
|
+
const error = JSON.stringify({[key]: value})
|
|
48
|
+
return `error ${error} cannot be converted to a graph`
|
|
45
49
|
}
|
|
46
50
|
if (keys.length !== 0) return keys
|
|
47
51
|
}
|
|
48
|
-
|
|
52
|
+
const error = JSON.stringify(data)
|
|
53
|
+
return `error ${error} cannot be converted to a graph`
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
const api = ctxid => {
|
|
52
|
-
const get = (lex, soul, ack) => {
|
|
53
|
-
wire.get(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
const get = (lex, soul, ack, _opt) => {
|
|
58
|
+
wire.get(
|
|
59
|
+
utils.obj.put(lex, "#", soul),
|
|
60
|
+
async msg => {
|
|
61
|
+
if (msg.err) console.log(msg.err)
|
|
62
|
+
if (msg.put && msg.put[soul]) {
|
|
63
|
+
delete msg.put[soul]._
|
|
64
|
+
delete msg.put[soul][utils.userPublicKey]
|
|
65
|
+
delete msg.put[soul][utils.userSignature]
|
|
66
|
+
// Resolve any rels on the node before returning to the user.
|
|
67
|
+
for (const key of Object.keys(msg.put[soul])) {
|
|
68
|
+
const id = utils.rel.is(msg.put[soul][key])
|
|
69
|
+
if (id) {
|
|
70
|
+
const data = await new Promise(res => {
|
|
71
|
+
const _ctxid = utils.text.random()
|
|
72
|
+
allctx.set(_ctxid, {chain: [{item: null, soul: id}]})
|
|
73
|
+
api(_ctxid).next(null, res)
|
|
74
|
+
})
|
|
75
|
+
msg.put[soul][key] = data
|
|
76
|
+
}
|
|
68
77
|
}
|
|
78
|
+
ack(msg.put[soul])
|
|
79
|
+
} else {
|
|
80
|
+
// No data callback.
|
|
81
|
+
ack(null)
|
|
69
82
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
ack(null)
|
|
74
|
-
}
|
|
75
|
-
})
|
|
83
|
+
},
|
|
84
|
+
_opt,
|
|
85
|
+
)
|
|
76
86
|
}
|
|
77
87
|
|
|
78
|
-
const graph = async (soul, data, cb) => {
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (opt.secure) {
|
|
83
|
-
cb(`error putting data on ${soul}: user required in secure mode`)
|
|
84
|
-
return null
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return utils.graph(soul, data)
|
|
88
|
+
const graph = async (soul, data, userctx, cb) => {
|
|
89
|
+
if (userctx) {
|
|
90
|
+
const signed = await SEA.sign(data, userctx)
|
|
91
|
+
return utils.graph(soul, signed.m, signed.s, userctx.pub)
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
if (
|
|
91
|
-
cb
|
|
94
|
+
if (opt.secure) {
|
|
95
|
+
if (!cb) cb = console.log
|
|
96
|
+
cb(`error putting data on ${soul}: user required in secure mode`)
|
|
92
97
|
return null
|
|
93
98
|
}
|
|
94
99
|
|
|
95
|
-
|
|
96
|
-
return utils.graph(soul, signed.m, signed.s, user.is.pub)
|
|
100
|
+
return utils.graph(soul, data)
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
const done = data => {
|
|
100
104
|
const ctx = allctx.get(ctxid)
|
|
101
|
-
if (ctx && typeof ctx.cb !== "undefined")
|
|
102
|
-
|
|
105
|
+
if (ctx && typeof ctx.cb !== "undefined") {
|
|
106
|
+
// Use a timeout so that the context can be removed before data is
|
|
107
|
+
// returned to the callback (allows nested get calls).
|
|
108
|
+
setTimeout(() => ctx.cb(data), 1)
|
|
109
|
+
} else if (data) {
|
|
110
|
+
console.log("error no callback for data", data, "ctx", ctx)
|
|
111
|
+
}
|
|
103
112
|
// A context updated by "on" should only be removed by "off".
|
|
104
113
|
if (ctx && !ctx.on) allctx.delete(ctxid)
|
|
105
114
|
}
|
|
106
115
|
|
|
107
116
|
const resolve = (request, cb) => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
if (!request) {
|
|
118
|
+
console.log("error resolve request parameter required")
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const get = typeof request.get !== "undefined"
|
|
123
|
+
const put = typeof request.put !== "undefined"
|
|
124
|
+
const on = typeof request.on !== "undefined"
|
|
125
|
+
const off = typeof request.off !== "undefined"
|
|
112
126
|
|
|
113
127
|
let found = false
|
|
114
128
|
const ctx = allctx.get(ctxid)
|
|
@@ -123,34 +137,45 @@ const Holster = opt => {
|
|
|
123
137
|
// Found a soul that needs resolving, need the previous context
|
|
124
138
|
// (ie the parent node) to find a soul relation for it.
|
|
125
139
|
const {item, soul} = ctx.chain[i - 1]
|
|
126
|
-
|
|
140
|
+
// If this is a user context or using secure mode then need to get the
|
|
141
|
+
// whole node for verification.
|
|
142
|
+
const lex =
|
|
143
|
+
ctx.user || opt.secure ? {"#": soul} : {"#": soul, ".": item}
|
|
144
|
+
wire.get(lex, async msg => {
|
|
127
145
|
if (msg.err) {
|
|
128
|
-
|
|
146
|
+
if (ctx.user || opt.secure) {
|
|
147
|
+
console.log(`error getting ${soul}: ${msg.err}`)
|
|
148
|
+
} else {
|
|
149
|
+
console.log(`error getting ${item} on ${soul}: ${msg.err}`)
|
|
150
|
+
}
|
|
129
151
|
if (cb) cb(null)
|
|
130
152
|
return
|
|
131
153
|
}
|
|
132
154
|
|
|
133
|
-
|
|
155
|
+
let node = msg.put && msg.put[soul]
|
|
134
156
|
if (node && typeof node[item] !== "undefined") {
|
|
135
157
|
let id = utils.rel.is(node[item])
|
|
136
158
|
if (id) {
|
|
137
159
|
ctx.chain[i].soul = id
|
|
138
|
-
|
|
139
|
-
allctx.set(ctxid, {chain: ctx.chain, cb: ctx.cb})
|
|
160
|
+
allctx.set(ctxid, {...ctx})
|
|
140
161
|
// Call api again using the updated context.
|
|
141
|
-
if (get)
|
|
142
|
-
|
|
143
|
-
else if (
|
|
144
|
-
|
|
162
|
+
if (get) {
|
|
163
|
+
api(ctxid).next(null, request.get, cb, request._opt)
|
|
164
|
+
} else if (put) {
|
|
165
|
+
api(ctxid).put(request.put, cb)
|
|
166
|
+
} else if (on) {
|
|
167
|
+
api(ctxid).on(request.on, cb, request._get, request._opt)
|
|
168
|
+
} else if (off) {
|
|
169
|
+
api(ctxid).off(cb)
|
|
170
|
+
}
|
|
145
171
|
} else if (get) {
|
|
146
|
-
// Request was not for a node, return
|
|
147
|
-
// soul.
|
|
172
|
+
// Request was not for a node, return property on current soul.
|
|
148
173
|
cb(node[item])
|
|
149
174
|
} else if (put) {
|
|
150
175
|
// Request was chained before put, so rel doesn't exist yet.
|
|
151
176
|
id = utils.text.random()
|
|
152
|
-
|
|
153
|
-
const g = await graph(soul,
|
|
177
|
+
node[item] = utils.rel.ify(id)
|
|
178
|
+
const g = await graph(soul, node, ctx.user, cb)
|
|
154
179
|
if (g === null) return
|
|
155
180
|
|
|
156
181
|
wire.put(g, err => {
|
|
@@ -163,16 +188,31 @@ const Holster = opt => {
|
|
|
163
188
|
api(ctxid).put(request.put, cb)
|
|
164
189
|
})
|
|
165
190
|
} else if (on) {
|
|
166
|
-
|
|
191
|
+
// Allow listening to a node that doesn't exist.
|
|
167
192
|
cb(null)
|
|
168
193
|
} else if (off) {
|
|
169
|
-
|
|
194
|
+
// Allow stop listening to a node that doesn't exist.
|
|
170
195
|
if (cb) cb(null)
|
|
171
196
|
}
|
|
172
197
|
} else if (put) {
|
|
173
|
-
|
|
198
|
+
// Request was chained before put, so rel doesn't exist yet.
|
|
199
|
+
const id = utils.text.random()
|
|
200
|
+
if (!node) node = {}
|
|
201
|
+
node[item] = utils.rel.ify(id)
|
|
202
|
+
const g = await graph(soul, node, ctx.user, cb)
|
|
203
|
+
if (g === null) return
|
|
204
|
+
|
|
205
|
+
wire.put(g, err => {
|
|
206
|
+
if (err) {
|
|
207
|
+
cb(`error putting ${item} on ${soul}: ${err}`)
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
ctx.chain[i].soul = id
|
|
212
|
+
api(ctxid).put(request.put, cb)
|
|
213
|
+
})
|
|
174
214
|
} else {
|
|
175
|
-
|
|
215
|
+
// Allow querying a node that doesn't exist.
|
|
176
216
|
if (cb) cb(null)
|
|
177
217
|
}
|
|
178
218
|
})
|
|
@@ -194,46 +234,45 @@ const Holster = opt => {
|
|
|
194
234
|
}
|
|
195
235
|
|
|
196
236
|
return {
|
|
197
|
-
get: (key, lex, cb) => {
|
|
237
|
+
get: (key, lex, cb, _opt) => {
|
|
198
238
|
if (typeof lex === "function") {
|
|
239
|
+
_opt = cb
|
|
199
240
|
cb = lex
|
|
200
241
|
lex = null
|
|
201
242
|
}
|
|
202
243
|
if (key === null || key === "" || key === "_") {
|
|
244
|
+
console.log("error please provide a key")
|
|
203
245
|
if (cb) cb(null)
|
|
204
246
|
return
|
|
205
247
|
}
|
|
206
248
|
|
|
207
249
|
// lex requires a callback as it's not included in the chain below.
|
|
208
|
-
if (lex &&
|
|
209
|
-
console.log("lex requires a callback function")
|
|
250
|
+
if (lex && typeof cb !== "function") {
|
|
251
|
+
console.log("error lex requires a callback function")
|
|
210
252
|
return
|
|
211
253
|
}
|
|
212
254
|
|
|
213
255
|
// Top level keys are added to a root node so their values don't need
|
|
214
|
-
// to be objects
|
|
215
|
-
// user.ctx is set.
|
|
216
|
-
const root = user.ctx ? user.ctx : "root"
|
|
217
|
-
|
|
256
|
+
// to be objects.
|
|
218
257
|
ctxid = utils.text.random()
|
|
219
|
-
allctx.set(ctxid, {chain: [{item: key, soul: root}], cb: cb})
|
|
258
|
+
allctx.set(ctxid, {chain: [{item: key, soul: "root"}], cb: cb})
|
|
220
259
|
if (!cb) return api(ctxid)
|
|
221
260
|
|
|
222
261
|
// When there's a callback need to resolve the context first.
|
|
223
|
-
const {soul} = resolve({get: lex}, done)
|
|
224
|
-
if (soul) get(lex, soul, done)
|
|
262
|
+
const {soul} = resolve({get: lex, _opt: _opt}, done)
|
|
263
|
+
if (soul) get(lex, soul, done, _opt)
|
|
225
264
|
},
|
|
226
|
-
next: (key, lex, cb) => {
|
|
265
|
+
next: (key, lex, cb, _opt) => {
|
|
227
266
|
const ack = data => {
|
|
228
267
|
cb ? cb(data) : done(data)
|
|
229
268
|
}
|
|
230
|
-
|
|
231
269
|
if (typeof lex === "function") {
|
|
270
|
+
_opt = cb
|
|
232
271
|
cb = lex
|
|
233
272
|
lex = null
|
|
234
273
|
}
|
|
235
274
|
if (!ctxid) {
|
|
236
|
-
console.log("please provide a key using get(key)")
|
|
275
|
+
console.log("error please provide a key using get(key)")
|
|
237
276
|
ack(null)
|
|
238
277
|
return
|
|
239
278
|
}
|
|
@@ -244,8 +283,8 @@ const Holster = opt => {
|
|
|
244
283
|
}
|
|
245
284
|
|
|
246
285
|
// lex requires a callback as it's not included in the chain below.
|
|
247
|
-
if (lex &&
|
|
248
|
-
console.log("lex requires a callback function")
|
|
286
|
+
if (lex && typeof cb !== "function") {
|
|
287
|
+
console.log("error lex requires a callback function")
|
|
249
288
|
return
|
|
250
289
|
}
|
|
251
290
|
|
|
@@ -265,8 +304,8 @@ const Holster = opt => {
|
|
|
265
304
|
if (!ctx.cb) return api(ctxid)
|
|
266
305
|
|
|
267
306
|
// When there's a callback need to resolve the context first.
|
|
268
|
-
const {soul} = resolve({get: lex}, ack)
|
|
269
|
-
if (soul) get(lex, soul, ack)
|
|
307
|
+
const {soul} = resolve({get: lex, _opt: _opt}, ack)
|
|
308
|
+
if (soul) get(lex, soul, ack, _opt)
|
|
270
309
|
},
|
|
271
310
|
put: (data, set, cb) => {
|
|
272
311
|
if (typeof set === "function") {
|
|
@@ -310,17 +349,23 @@ const Holster = opt => {
|
|
|
310
349
|
// When result is true data is a property to put on the current soul.
|
|
311
350
|
// Need to check if item is a rel and also set the node to null. (This
|
|
312
351
|
// applies for any update from a rel to a property, not just null.)
|
|
313
|
-
|
|
352
|
+
// If using secure mode need to get the whole node for verification.
|
|
353
|
+
const lex =
|
|
354
|
+
ctx.user || opt.secure ? {"#": soul} : {"#": soul, ".": item}
|
|
355
|
+
wire.get(lex, async msg => {
|
|
314
356
|
if (msg.err) {
|
|
315
|
-
|
|
357
|
+
ack(`error getting ${soul}: ${msg.err}`)
|
|
316
358
|
return
|
|
317
359
|
}
|
|
318
360
|
|
|
319
|
-
|
|
361
|
+
let node = msg.put && msg.put[soul]
|
|
362
|
+
const current = node && node[item]
|
|
320
363
|
const id = utils.rel.is(current)
|
|
321
364
|
if (!id) {
|
|
322
365
|
// Not a rel, can just put the data.
|
|
323
|
-
|
|
366
|
+
if (!node) node = {}
|
|
367
|
+
node[item] = data
|
|
368
|
+
const g = await graph(soul, node, ctx.user, ack)
|
|
324
369
|
if (g === null) return
|
|
325
370
|
|
|
326
371
|
wire.put(g, ack)
|
|
@@ -329,23 +374,29 @@ const Holster = opt => {
|
|
|
329
374
|
|
|
330
375
|
wire.get({"#": id}, async msg => {
|
|
331
376
|
if (msg.err) {
|
|
332
|
-
|
|
377
|
+
ack(`error getting ${id}: ${msg.err}`)
|
|
333
378
|
return
|
|
334
379
|
}
|
|
335
380
|
|
|
336
381
|
if (!msg.put || !msg.put[id]) {
|
|
337
|
-
|
|
382
|
+
ack(`error ${id} not found`)
|
|
338
383
|
return
|
|
339
384
|
}
|
|
340
385
|
|
|
341
|
-
delete msg.put[id]._
|
|
342
386
|
// null each of the properties on the node before putting data.
|
|
343
387
|
for (const key of Object.keys(msg.put[id])) {
|
|
344
|
-
if (
|
|
388
|
+
if (
|
|
389
|
+
key === "_" ||
|
|
390
|
+
key === utils.userPublicKey ||
|
|
391
|
+
key === utils.userSignature
|
|
392
|
+
) {
|
|
393
|
+
continue
|
|
394
|
+
}
|
|
345
395
|
|
|
346
396
|
const err = await new Promise(res => {
|
|
347
397
|
const _ctxid = utils.text.random()
|
|
348
|
-
|
|
398
|
+
const chain = [{item: key, soul: id}]
|
|
399
|
+
allctx.set(_ctxid, {chain: chain, user: ctx.user})
|
|
349
400
|
api(_ctxid).put(null, res)
|
|
350
401
|
})
|
|
351
402
|
if (err) {
|
|
@@ -353,7 +404,9 @@ const Holster = opt => {
|
|
|
353
404
|
return
|
|
354
405
|
}
|
|
355
406
|
}
|
|
356
|
-
|
|
407
|
+
if (!node) node = {}
|
|
408
|
+
node[item] = data
|
|
409
|
+
const g = await graph(soul, node, ctx.user, ack)
|
|
357
410
|
if (g === null) return
|
|
358
411
|
|
|
359
412
|
wire.put(g, ack)
|
|
@@ -364,18 +417,23 @@ const Holster = opt => {
|
|
|
364
417
|
|
|
365
418
|
// Otherwise put the data using the keys returned in result.
|
|
366
419
|
// Need to check if a rel has already been added on the current node.
|
|
367
|
-
|
|
420
|
+
// If using secure mode need to get the whole node for verification.
|
|
421
|
+
const lex =
|
|
422
|
+
ctx.user || opt.secure ? {"#": soul} : {"#": soul, ".": item}
|
|
423
|
+
wire.get(lex, async msg => {
|
|
368
424
|
if (msg.err) {
|
|
369
425
|
ack(`error getting ${soul}.${item}: ${msg.err}`)
|
|
370
426
|
return
|
|
371
427
|
}
|
|
372
428
|
|
|
373
|
-
|
|
429
|
+
let node = msg.put && msg.put[soul]
|
|
430
|
+
const current = node && node[item]
|
|
374
431
|
const id = utils.rel.is(current)
|
|
375
432
|
if (!id) {
|
|
376
433
|
// The current rel doesn't exist, so add it first.
|
|
377
|
-
|
|
378
|
-
|
|
434
|
+
if (!node) node = {}
|
|
435
|
+
node[item] = utils.rel.ify(utils.text.random())
|
|
436
|
+
const g = await graph(soul, node, ctx.user, ack)
|
|
379
437
|
if (g === null) return
|
|
380
438
|
|
|
381
439
|
wire.put(g, err => {
|
|
@@ -384,27 +442,26 @@ const Holster = opt => {
|
|
|
384
442
|
} else {
|
|
385
443
|
const _ctxid = utils.text.random()
|
|
386
444
|
const chain = [{item: item, soul: soul}]
|
|
387
|
-
// Pass the previous context's callback
|
|
388
|
-
allctx.set(_ctxid, {chain: chain, cb: ctx.cb})
|
|
445
|
+
// Pass on the previous context's callback and user flag here.
|
|
446
|
+
allctx.set(_ctxid, {chain: chain, user: ctx.user, cb: ctx.cb})
|
|
389
447
|
api(_ctxid).put(data)
|
|
390
448
|
}
|
|
391
449
|
})
|
|
392
450
|
return
|
|
393
451
|
}
|
|
394
452
|
|
|
395
|
-
|
|
396
|
-
const update = {}
|
|
453
|
+
const update = []
|
|
397
454
|
for (const key of result) {
|
|
398
455
|
const err = await new Promise(res => {
|
|
399
|
-
if (utils.obj.is(data[key])) {
|
|
456
|
+
if (utils.obj.is(data[key]) && !utils.rel.is(data[key])) {
|
|
400
457
|
// Use the current rel as the context for nested objects.
|
|
401
458
|
const _ctxid = utils.text.random()
|
|
402
|
-
|
|
459
|
+
const chain = [{item: key, soul: id}]
|
|
460
|
+
allctx.set(_ctxid, {chain: chain, user: ctx.user})
|
|
403
461
|
api(_ctxid).put(data[key], res)
|
|
404
462
|
} else {
|
|
405
|
-
put
|
|
406
|
-
|
|
407
|
-
update[key] = data[key]
|
|
463
|
+
// Group the rest of the updates for put below.
|
|
464
|
+
update.push(key)
|
|
408
465
|
res(null)
|
|
409
466
|
}
|
|
410
467
|
})
|
|
@@ -413,32 +470,52 @@ const Holster = opt => {
|
|
|
413
470
|
return
|
|
414
471
|
}
|
|
415
472
|
}
|
|
416
|
-
if (put) {
|
|
417
|
-
const g = await graph(id, update, ack)
|
|
418
|
-
if (g === null) return
|
|
419
473
|
|
|
420
|
-
|
|
421
|
-
} else {
|
|
422
|
-
// Callback on behalf of nested objects.
|
|
474
|
+
if (update.length === 0) {
|
|
423
475
|
ack(null)
|
|
476
|
+
return
|
|
424
477
|
}
|
|
478
|
+
|
|
479
|
+
// The nested objects created above will also have rels on the parent
|
|
480
|
+
// object, so fetch the node so the rest of the updates can be added.
|
|
481
|
+
wire.get({"#": id}, async msg => {
|
|
482
|
+
if (msg.err) {
|
|
483
|
+
ack(`error getting ${id}: ${msg.err}`)
|
|
484
|
+
return
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
let node = msg.put && msg.put[id]
|
|
488
|
+
if (!node) node = {}
|
|
489
|
+
update.forEach(key => {
|
|
490
|
+
node[key] = data[key]
|
|
491
|
+
})
|
|
492
|
+
const g = await graph(id, node, ctx.user, ack)
|
|
493
|
+
if (g === null) return
|
|
494
|
+
|
|
495
|
+
wire.put(g, ack)
|
|
496
|
+
})
|
|
425
497
|
})
|
|
426
498
|
},
|
|
427
|
-
on: (lex, cb) => {
|
|
499
|
+
on: (lex, cb, _get, _opt) => {
|
|
428
500
|
if (typeof lex === "function") {
|
|
501
|
+
_opt = _get
|
|
502
|
+
_get = cb
|
|
429
503
|
cb = lex
|
|
430
504
|
lex = null
|
|
431
505
|
}
|
|
432
|
-
if (
|
|
506
|
+
if (typeof cb !== "function") {
|
|
507
|
+
console.log("error on() requires a callback function")
|
|
508
|
+
return
|
|
509
|
+
}
|
|
433
510
|
|
|
434
511
|
if (!ctxid) {
|
|
435
|
-
console.log("please provide a key using get(key)")
|
|
512
|
+
console.log("error please provide a key using get(key)")
|
|
436
513
|
cb(null)
|
|
437
514
|
return
|
|
438
515
|
}
|
|
439
516
|
|
|
440
517
|
// Resolve the current context before adding event listener.
|
|
441
|
-
const {item, soul} = resolve({on: lex}, cb)
|
|
518
|
+
const {item, soul} = resolve({on: lex, _get: _get, _opt: _opt}, cb)
|
|
442
519
|
if (!soul) return
|
|
443
520
|
|
|
444
521
|
// Flag that this context is set from on and shouldn't be removed.
|
|
@@ -462,12 +539,12 @@ const Holster = opt => {
|
|
|
462
539
|
if (lex) lex = utils.obj.put(lex, "#", soul)
|
|
463
540
|
else lex = {"#": soul, ".": item}
|
|
464
541
|
}
|
|
465
|
-
wire.on(lex, map.get(cb))
|
|
542
|
+
wire.on(lex, map.get(cb), _get, _opt)
|
|
466
543
|
})
|
|
467
544
|
},
|
|
468
545
|
off: cb => {
|
|
469
546
|
if (!ctxid) {
|
|
470
|
-
console.log("please provide a key using get(key)")
|
|
547
|
+
console.log("error please provide a key using get(key)")
|
|
471
548
|
if (cb) cb(null)
|
|
472
549
|
return
|
|
473
550
|
}
|
|
@@ -491,13 +568,61 @@ const Holster = opt => {
|
|
|
491
568
|
allctx.delete(ctxid)
|
|
492
569
|
})
|
|
493
570
|
},
|
|
494
|
-
user:
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
571
|
+
user: () => {
|
|
572
|
+
if (!user.get) {
|
|
573
|
+
// Return the combined Holster and User APIs.
|
|
574
|
+
Object.assign(user, api())
|
|
575
|
+
// Need to provide a user specific get() function to know if user
|
|
576
|
+
// context should be checked.
|
|
577
|
+
user.get = (keys, lex, cb, _opt) => {
|
|
578
|
+
if (typeof lex === "function") {
|
|
579
|
+
_opt = cb
|
|
580
|
+
cb = lex
|
|
581
|
+
lex = null
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
let pub = null
|
|
585
|
+
let key = null
|
|
586
|
+
if (user.is) pub = user.is.pub
|
|
587
|
+
if (typeof keys === "string") {
|
|
588
|
+
key = keys
|
|
589
|
+
} else if (keys instanceof Array) {
|
|
590
|
+
if (keys.length === 2) {
|
|
591
|
+
pub = keys[0]
|
|
592
|
+
key = keys[1]
|
|
593
|
+
} else if (keys.length === 1) {
|
|
594
|
+
key = keys[0]
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (!pub) {
|
|
598
|
+
console.log("error please log in or provide a public key")
|
|
599
|
+
if (cb) cb(null)
|
|
600
|
+
return
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
if (key === null || key === "" || key === "_") {
|
|
604
|
+
console.log("error please provide a key")
|
|
605
|
+
if (cb) cb(null)
|
|
606
|
+
return
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// lex requires a callback as it's not included in the chain below.
|
|
610
|
+
if (lex && !cb) {
|
|
611
|
+
console.log("error lex requires a callback function")
|
|
612
|
+
return
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
ctxid = utils.text.random()
|
|
616
|
+
const chain = [{item: key, soul: "~" + pub}]
|
|
617
|
+
allctx.set(ctxid, {chain: chain, user: user.is, cb: cb})
|
|
618
|
+
if (!cb) return api(ctxid)
|
|
619
|
+
|
|
620
|
+
// When there's a callback need to resolve the context first.
|
|
621
|
+
const {soul} = resolve({get: lex}, done)
|
|
622
|
+
if (soul) get(lex, soul, done, _opt)
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return user
|
|
501
626
|
},
|
|
502
627
|
// Allow the wire spec to be used via holster.
|
|
503
628
|
wire: wire,
|
package/src/index.js
CHANGED
package/src/sea-utils.js
CHANGED
|
@@ -2,7 +2,7 @@ import SafeBuffer from "./buffer.js"
|
|
|
2
2
|
|
|
3
3
|
const isNode = typeof document === "undefined"
|
|
4
4
|
const crypto = isNode
|
|
5
|
-
? (await import("node:crypto")).webcrypto
|
|
5
|
+
? (await import(/*webpackIgnore: true*/ "node:crypto")).webcrypto
|
|
6
6
|
: globalThis.crypto
|
|
7
7
|
export const subtle = crypto.subtle
|
|
8
8
|
|
package/src/sea.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {userPublicKey} from "./utils.js"
|
|
1
|
+
import {userPublicKey, userSignature} from "./utils.js"
|
|
2
2
|
import * as utils from "./sea-utils.js"
|
|
3
3
|
import SafeBuffer from "./buffer.js"
|
|
4
4
|
|
|
@@ -117,8 +117,10 @@ const SEA = {
|
|
|
117
117
|
} else {
|
|
118
118
|
// Allow data to be passed in with graph meta data,
|
|
119
119
|
// (which should not be part of signature, so not verified).
|
|
120
|
-
for (const k of Object.keys(signed.m)) {
|
|
121
|
-
if (k !== "_" && k != userPublicKey
|
|
120
|
+
for (const k of Object.keys(signed.m).sort()) {
|
|
121
|
+
if (k !== "_" && k != userPublicKey && k != userSignature) {
|
|
122
|
+
msg[k] = signed.m[k]
|
|
123
|
+
}
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
126
|
const hash = await utils.sha256(msg)
|
|
@@ -139,7 +141,17 @@ const SEA = {
|
|
|
139
141
|
return null
|
|
140
142
|
}
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
let msg = {}
|
|
145
|
+
if (typeof data === "string") {
|
|
146
|
+
msg = data
|
|
147
|
+
} else {
|
|
148
|
+
const check = utils.parse(data)
|
|
149
|
+
for (const k of Object.keys(check).sort()) {
|
|
150
|
+
if (k !== "_" && k != userPublicKey && k != userSignature) {
|
|
151
|
+
msg[k] = check[k]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
143
155
|
const hash = await utils.sha256(msg)
|
|
144
156
|
const jwk = utils.jwk(pair.pub, pair.priv)
|
|
145
157
|
const alg = {name: "ECDSA", namedCurve: "P-256"}
|
package/src/store.js
CHANGED
|
@@ -3,7 +3,7 @@ import Radix from "./radix.js"
|
|
|
3
3
|
import * as utils from "./utils.js"
|
|
4
4
|
|
|
5
5
|
const isNode = typeof document === "undefined"
|
|
6
|
-
const fs = isNode ? await import("node:fs") : undefined
|
|
6
|
+
const fs = isNode ? await import(/*webpackIgnore: true*/ "node:fs") : undefined
|
|
7
7
|
|
|
8
8
|
// ASCII character for enquiry.
|
|
9
9
|
const enq = String.fromCharCode(5)
|