@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/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 an item name"
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
- return `error {${key}:${value}} cannot be converted to graph`
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
- return `error ${data} cannot be converted to a graph`
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(utils.obj.put(lex, "#", soul), async msg => {
54
- if (msg.err) console.log(msg.err)
55
- if (msg.put && msg.put[soul]) {
56
- delete msg.put[soul]._
57
- delete msg.put[soul][utils.userPublicKey]
58
- // Resolve any rels on the node before returning to the user.
59
- for (const key of Object.keys(msg.put[soul])) {
60
- const id = utils.rel.is(msg.put[soul][key])
61
- if (id) {
62
- const data = await new Promise(res => {
63
- const _ctxid = utils.text.random()
64
- allctx.set(_ctxid, {chain: [{item: null, soul: id}]})
65
- api(_ctxid).next(null, res)
66
- })
67
- msg.put[soul][key] = data
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
- ack(msg.put[soul])
71
- } else {
72
- // No data callback.
73
- ack(null)
74
- }
75
- })
83
+ },
84
+ _opt,
85
+ )
76
86
  }
77
87
 
78
- const graph = async (soul, data, cb) => {
79
- if (!cb) cb = console.log
80
-
81
- if (!user.is) {
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 (!user.is) {
91
- cb(`error putting data on ${soul}: user not authenticated`)
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
- const signed = await SEA.sign(data, user.is)
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") ctx.cb(data)
102
- else if (data) console.log(data)
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
- const get = request && typeof request.get !== "undefined"
109
- const put = request && typeof request.put !== "undefined"
110
- const on = request && typeof request.on !== "undefined"
111
- const off = request && typeof request.off !== "undefined"
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
- wire.get({"#": soul, ".": item}, async msg => {
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
- console.log(`error getting ${item} on ${soul}: ${msg.err}`)
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
- const node = msg.put && msg.put[soul]
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
- // Not sure why the map needs to be set rather than just ctx?
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) api(ctxid).next(null, request.get, cb)
142
- else if (put) api(ctxid).put(request.put, cb)
143
- else if (on) api(ctxid).on(request.on, cb)
144
- else if (off) api(ctxid).off(cb)
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 a property on the current
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
- const rel = {[item]: utils.rel.ify(id)}
153
- const g = await graph(soul, rel, cb)
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
- console.log(`error resolving on for ${item} on ${soul}`)
191
+ // Allow listening to a node that doesn't exist.
167
192
  cb(null)
168
193
  } else if (off) {
169
- console.log(`error resolving off for ${item} on ${soul}`)
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
- cb(`error ${item} not found on ${soul}`)
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
- console.log(`error ${item} not found on ${soul}`)
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 && !cb) {
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, the user's public key is used as the root node when
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 && !cb) {
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
- wire.get({"#": soul, ".": item}, async msg => {
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
- console.log(`error getting ${soul}: ${msg.err}`)
357
+ ack(`error getting ${soul}: ${msg.err}`)
316
358
  return
317
359
  }
318
360
 
319
- const current = msg.put && msg.put[soul] && msg.put[soul][item]
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
- const g = await graph(soul, {[item]: data}, ack)
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
- console.log(`error getting ${id}: ${msg.err}`)
377
+ ack(`error getting ${id}: ${msg.err}`)
333
378
  return
334
379
  }
335
380
 
336
381
  if (!msg.put || !msg.put[id]) {
337
- console.log(`error ${id} not found`)
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 (key === utils.userPublicKey) continue
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
- allctx.set(_ctxid, {chain: [{item: key, soul: id}]})
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
- const g = await graph(soul, {[item]: data}, ack)
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
- wire.get({"#": soul, ".": item}, async msg => {
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
- const current = msg.put && msg.put[soul] && msg.put[soul][item]
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
- const rel = {[item]: utils.rel.ify(utils.text.random())}
378
- const g = await graph(soul, rel, ack)
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 on here.
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
- let put = false
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
- allctx.set(_ctxid, {chain: [{item: key, soul: id}]})
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 = true
406
- // Group other properties into one update.
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
- wire.put(g, ack)
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 (!cb) return
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: pub => {
495
- // Return the combined Holster and User APIs. Passing in a public key
496
- // will set the user context to that key, otherwise user.ctx is set when
497
- // a user logs in so that their public key will be used as the root node
498
- // in get(), also put() will sign all graph updates for verification.
499
- if (pub) user.ctx = "~" + pub
500
- return Object.assign(user, api())
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
@@ -3,7 +3,6 @@ import path from "path"
3
3
  import {fileURLToPath} from "url"
4
4
  import Holster from "./holster.js"
5
5
 
6
- // TODO: pass in opt for websocket url, etc.
7
6
  const holster = Holster()
8
7
 
9
8
  // Note that express is only used here to serve the examples folder. It is not
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) msg[k] = signed.m[k]
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
- const msg = utils.parse(data)
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)