@interop/wallet-core 0.94.0 → 0.95.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.
Files changed (100) hide show
  1. package/README.md +21 -20
  2. package/dist/clientAnnex/mend.js +4 -1
  3. package/dist/clientAnnex/mend.js.map +1 -1
  4. package/dist/clients/index.d.ts +3 -2
  5. package/dist/clients/index.d.ts.map +1 -1
  6. package/dist/clients/index.js +3 -2
  7. package/dist/clients/index.js.map +1 -1
  8. package/dist/clients/listing.d.ts +19 -12
  9. package/dist/clients/listing.d.ts.map +1 -1
  10. package/dist/clients/listing.js +69 -22
  11. package/dist/clients/listing.js.map +1 -1
  12. package/dist/connections/didKey.d.ts +25 -0
  13. package/dist/connections/didKey.d.ts.map +1 -0
  14. package/dist/connections/didKey.js +49 -0
  15. package/dist/connections/didKey.js.map +1 -0
  16. package/dist/connections/entry.d.ts +226 -0
  17. package/dist/connections/entry.d.ts.map +1 -0
  18. package/dist/connections/entry.js +287 -0
  19. package/dist/connections/entry.js.map +1 -0
  20. package/dist/connections/errors.d.ts +33 -0
  21. package/dist/connections/errors.d.ts.map +1 -0
  22. package/dist/connections/errors.js +36 -0
  23. package/dist/connections/errors.js.map +1 -0
  24. package/dist/connections/grants.d.ts +94 -0
  25. package/dist/connections/grants.d.ts.map +1 -0
  26. package/dist/connections/grants.js +120 -0
  27. package/dist/connections/grants.js.map +1 -0
  28. package/dist/connections/index.d.ts +47 -0
  29. package/dist/connections/index.d.ts.map +1 -0
  30. package/dist/connections/index.js +40 -0
  31. package/dist/connections/index.js.map +1 -0
  32. package/dist/connections/read.d.ts +82 -0
  33. package/dist/connections/read.d.ts.map +1 -0
  34. package/dist/connections/read.js +100 -0
  35. package/dist/connections/read.js.map +1 -0
  36. package/dist/connections/resourceId.d.ts +36 -0
  37. package/dist/connections/resourceId.d.ts.map +1 -0
  38. package/dist/connections/resourceId.js +49 -0
  39. package/dist/connections/resourceId.js.map +1 -0
  40. package/dist/connections/store.d.ts +103 -0
  41. package/dist/connections/store.d.ts.map +1 -0
  42. package/dist/connections/store.js +67 -0
  43. package/dist/connections/store.js.map +1 -0
  44. package/dist/connections/upsert.d.ts +214 -0
  45. package/dist/connections/upsert.d.ts.map +1 -0
  46. package/dist/connections/upsert.js +468 -0
  47. package/dist/connections/upsert.js.map +1 -0
  48. package/dist/connections/writers.d.ts +217 -0
  49. package/dist/connections/writers.d.ts.map +1 -0
  50. package/dist/connections/writers.js +485 -0
  51. package/dist/connections/writers.js.map +1 -0
  52. package/dist/enrollment/onboardingResponse.d.ts +3 -3
  53. package/dist/enrollment/onboardingResponse.d.ts.map +1 -1
  54. package/dist/enrollment/onboardingResponse.js +17 -13
  55. package/dist/enrollment/onboardingResponse.js.map +1 -1
  56. package/dist/keys/index.d.ts +0 -7
  57. package/dist/keys/index.d.ts.map +1 -1
  58. package/dist/keys/index.js +0 -6
  59. package/dist/keys/index.js.map +1 -1
  60. package/dist/labelText.d.ts +30 -3
  61. package/dist/labelText.d.ts.map +1 -1
  62. package/dist/labelText.js +35 -3
  63. package/dist/labelText.js.map +1 -1
  64. package/dist/menders/ids.d.ts +1 -1
  65. package/dist/menders/ids.d.ts.map +1 -1
  66. package/dist/menders/ids.js +7 -2
  67. package/dist/menders/ids.js.map +1 -1
  68. package/dist/space/collections.d.ts +15 -25
  69. package/dist/space/collections.d.ts.map +1 -1
  70. package/dist/space/collections.js +19 -29
  71. package/dist/space/collections.js.map +1 -1
  72. package/dist/space/index.d.ts +4 -3
  73. package/dist/space/index.d.ts.map +1 -1
  74. package/dist/space/index.js +4 -3
  75. package/dist/space/index.js.map +1 -1
  76. package/package.json +8 -8
  77. package/dist/keys/clientLabels.d.ts +0 -85
  78. package/dist/keys/clientLabels.d.ts.map +0 -1
  79. package/dist/keys/clientLabels.js +0 -96
  80. package/dist/keys/clientLabels.js.map +0 -1
  81. package/dist/keys/wasLabelsStore.d.ts +0 -33
  82. package/dist/keys/wasLabelsStore.d.ts.map +0 -1
  83. package/dist/keys/wasLabelsStore.js +0 -35
  84. package/dist/keys/wasLabelsStore.js.map +0 -1
  85. package/dist/writers/entry.d.ts +0 -95
  86. package/dist/writers/entry.d.ts.map +0 -1
  87. package/dist/writers/entry.js +0 -90
  88. package/dist/writers/entry.js.map +0 -1
  89. package/dist/writers/index.d.ts +0 -17
  90. package/dist/writers/index.d.ts.map +0 -1
  91. package/dist/writers/index.js +0 -14
  92. package/dist/writers/index.js.map +0 -1
  93. package/dist/writers/roster.d.ts +0 -152
  94. package/dist/writers/roster.d.ts.map +0 -1
  95. package/dist/writers/roster.js +0 -365
  96. package/dist/writers/roster.js.map +0 -1
  97. package/dist/writers/store.d.ts +0 -71
  98. package/dist/writers/store.d.ts.map +0 -1
  99. package/dist/writers/store.js +0 -55
  100. package/dist/writers/store.js.map +0 -1
@@ -0,0 +1,468 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The upsert helpers every flow writes a party's entry through:
6
+ * `recordGrants` at consent, `removeGrants` at an unshare or a torn
7
+ * consent's rollback, `retireConnection` when a relationship ends, and
8
+ * `setConnectionLabel` for the user's rename and the enrollment-time name.
9
+ *
10
+ * Each runs `writeConnection`, the one bounded compare-and-swap loop at a
11
+ * party's resource id, which the writer arm (`writers.ts`) runs too. It reads
12
+ * the entry, applies its change to the stored body, and writes under
13
+ * `ifMatch` (or creates under `ifNoneMatch`). A lost race re-reads and
14
+ * re-applies, up to three attempts, after which the last
15
+ * `PreconditionFailedError` is thrown. A helper changes only the members it
16
+ * owns, so a member a newer build added, on the entry or on a grant wrapper,
17
+ * is written back verbatim. A helper that finds a body it cannot parse, one
18
+ * whose `version` is above this build's, or one that does not belong at the
19
+ * id refuses to write, rather than treating the body as absent: overwriting
20
+ * it would wipe a newer build's grants.
21
+ */
22
+ import { NotSupportedError } from '@interop/was-client';
23
+ import { errorNameOf } from '../errorName.js';
24
+ import { normalizeDisplayName } from '../labelText.js';
25
+ import { signingKeyMultibaseOfDid } from './didKey.js';
26
+ import { CONNECTION_ENTRY_VERSION, GRANT_KINDS, isWritableConnectionEntry, newConnectionEntry, parseConnectionEntry, parseConnectionZcap } from './entry.js';
27
+ import { ConnectionKindMismatchError } from './errors.js';
28
+ import { connectionGrants, isTargetInSpace } from './grants.js';
29
+ import { claimedResourceId } from './read.js';
30
+ import { connectionResourceId } from './resourceId.js';
31
+ const PRECONDITION_FAILED_ERROR_NAME = 'PreconditionFailedError';
32
+ const WRITE_ATTEMPTS = 3;
33
+ /**
34
+ * Whether a store write lost a race. Matched by name, since the store is an
35
+ * injected seam that may raise from a second copy of was-client.
36
+ *
37
+ * @param err {unknown}
38
+ * @returns {boolean}
39
+ */
40
+ export function isLostConnectionRace(err) {
41
+ return errorNameOf(err) === PRECONDITION_FAILED_ERROR_NAME;
42
+ }
43
+ /**
44
+ * The ETag a write over an existing resource pins to. A read that carried
45
+ * none would send the write unconditionally, so it is refused instead.
46
+ *
47
+ * @param options {object}
48
+ * @param options.resourceId {string}
49
+ * @param [options.etag] {string}
50
+ * @returns {string}
51
+ */
52
+ function requireConnectionEtag({ resourceId, etag }) {
53
+ if (etag === undefined) {
54
+ throw new NotSupportedError(`Cannot update connections entry "${resourceId}": its read returned ` +
55
+ 'no ETag, so the write would go out unconditionally. A browser ' +
56
+ "client needs `ETag` in the server's `Access-Control-Expose-Headers`.");
57
+ }
58
+ return etag;
59
+ }
60
+ /**
61
+ * Reads a stored body as an entry this build may write over, or throws. The
62
+ * body must sit at the id its own members derive to, parse, and carry this
63
+ * build's `version`.
64
+ *
65
+ * @param options {object}
66
+ * @param options.resourceId {string}
67
+ * @param options.stored {object} the store's `get` result
68
+ * @param options.hmacKey {ConnectionIdKey}
69
+ * @returns {Promise<WritableConnection>}
70
+ */
71
+ async function writableConnection({ resourceId, stored, hmacKey }) {
72
+ const claimed = await claimedResourceId({ body: stored.body, hmacKey });
73
+ const entry = parseConnectionEntry(stored.body);
74
+ if (claimed !== resourceId || entry === undefined) {
75
+ throw new Error(`The connections entry at "${resourceId}" cannot be parsed as the ` +
76
+ 'entry for this id; this build refuses to write over it.');
77
+ }
78
+ if (!isWritableConnectionEntry(entry)) {
79
+ throw new Error(`The connections entry at "${resourceId}" carries version ` +
80
+ `${entry.version}, newer than this build's ` +
81
+ `${CONNECTION_ENTRY_VERSION}; this build refuses to write over it.`);
82
+ }
83
+ return {
84
+ entry,
85
+ body: stored.body,
86
+ ...(stored.etag !== undefined && { etag: stored.etag })
87
+ };
88
+ }
89
+ /**
90
+ * The bounded compare-and-swap loop every directory write runs at one
91
+ * resource id: the upsert helpers here and the writer arm in `writers.ts`.
92
+ * Each attempt reads the resource, hands `change` the writable entry (or
93
+ * `undefined` when none stands), and writes the body it returns under
94
+ * `ifMatch` (or creates it under `ifNoneMatch`). A `stop` ends the loop with
95
+ * that outcome and no write. A lost race re-reads and re-applies, and after
96
+ * the last attempt the last `PreconditionFailedError` is thrown. `change`
97
+ * may throw a refusal, which ends the loop the same way.
98
+ *
99
+ * A stored body this build cannot write over (unparseable, misplaced, or
100
+ * from a newer build) throws, unless `unwritable` names the outcome to
101
+ * resolve with instead.
102
+ *
103
+ * @param options {object}
104
+ * @param options.store {ConnectionsStore}
105
+ * @param options.hmacKey {ConnectionIdKey}
106
+ * @param options.resourceId {string}
107
+ * @param options.change {Function}
108
+ * @param [options.unwritable] {Stop} the outcome for a body this build
109
+ * cannot write over; omitted, such a body throws
110
+ * @returns {Promise<object>} the id and the outcome: `created`, `updated`,
111
+ * or the `stop` the callback returned
112
+ */
113
+ export async function writeConnection({ store, hmacKey, resourceId, change, unwritable }) {
114
+ let lastRace;
115
+ for (let attempt = 0; attempt < WRITE_ATTEMPTS; attempt++) {
116
+ const stored = await store.get({ resourceId });
117
+ let current;
118
+ if (stored !== undefined) {
119
+ try {
120
+ current = await writableConnection({ resourceId, stored, hmacKey });
121
+ }
122
+ catch (err) {
123
+ if (unwritable === undefined) {
124
+ throw err;
125
+ }
126
+ return { resourceId, outcome: unwritable };
127
+ }
128
+ }
129
+ const next = change(current);
130
+ if ('stop' in next) {
131
+ return { resourceId, outcome: next.stop };
132
+ }
133
+ try {
134
+ if (current === undefined) {
135
+ await store.put({ resourceId, body: next.body, ifNoneMatch: true });
136
+ return { resourceId, outcome: 'created' };
137
+ }
138
+ await store.put({
139
+ resourceId,
140
+ body: next.body,
141
+ ifMatch: requireConnectionEtag({ resourceId, etag: current.etag })
142
+ });
143
+ return { resourceId, outcome: 'updated' };
144
+ }
145
+ catch (err) {
146
+ if (!isLostConnectionRace(err)) {
147
+ throw err;
148
+ }
149
+ lastRace = err;
150
+ }
151
+ }
152
+ throw lastRace;
153
+ }
154
+ /**
155
+ * {@link writeConnection} for the helpers here, keyed by the party's DID. A
156
+ * helper with nothing to write stops with `absent` (no entry at the id) or
157
+ * `unchanged`.
158
+ *
159
+ * @param options {object}
160
+ * @param options.store {ConnectionsStore}
161
+ * @param options.hmacKey {ConnectionIdKey}
162
+ * @param options.did {string} the party's DID
163
+ * @param options.change {Function}
164
+ * @returns {Promise<ConnectionWriteResult>}
165
+ */
166
+ async function writePartyConnection({ store, hmacKey, did, change }) {
167
+ return writeConnection({
168
+ store,
169
+ hmacKey,
170
+ resourceId: await connectionResourceId({ hmacKey, did }),
171
+ change
172
+ });
173
+ }
174
+ /**
175
+ * Refuses a stored entry of another kind than the writing flow's.
176
+ *
177
+ * @param options {object}
178
+ * @param options.entry {ConnectionEntry}
179
+ * @param options.kind {string}
180
+ */
181
+ function assertKind({ entry, kind }) {
182
+ if (entry.kind !== kind) {
183
+ throw new ConnectionKindMismatchError({
184
+ expectedKind: kind,
185
+ foundKind: entry.kind
186
+ });
187
+ }
188
+ }
189
+ /**
190
+ * The capability of one grant to record, checked strictly: its known members
191
+ * well-formed, its `controller` the party's DID, its `invocationTarget` under
192
+ * this Space, its kind one this build writes. The target check is the same
193
+ * one every reader applies, so a grant that is stored is a grant the
194
+ * revocation index will see.
195
+ *
196
+ * @param options {object}
197
+ * @param options.did {string}
198
+ * @param options.spaceUrl {string}
199
+ * @param options.grant {object}
200
+ * @returns {ConnectionZcap}
201
+ */
202
+ function checkedGrant({ did, spaceUrl, grant }) {
203
+ const zcap = parseConnectionZcap(grant.zcap);
204
+ if (zcap === undefined) {
205
+ throw new TypeError('A grant to record must carry a capability with an id, a controller, ' +
206
+ 'and an invocation target.');
207
+ }
208
+ if (zcap.controller !== did) {
209
+ throw new TypeError(`A grant to record must be delegated to the party "${did}"; its ` +
210
+ `controller is "${zcap.controller}".`);
211
+ }
212
+ if (!isTargetInSpace({ target: zcap.invocationTarget, spaceUrl })) {
213
+ throw new TypeError('A grant to record must target this Space; its invocation target is ' +
214
+ `"${zcap.invocationTarget}".`);
215
+ }
216
+ if (!GRANT_KINDS.includes(grant.grantKind)) {
217
+ throw new TypeError(`Unknown grant kind "${grant.grantKind}".`);
218
+ }
219
+ return zcap;
220
+ }
221
+ /**
222
+ * Records a consent on the party's entry: creates the entry, or merges into
223
+ * it. Each new grant is added by its capability id (one already recorded is
224
+ * left as stored), `name` is set when it passes the display-name rule (left
225
+ * as it was otherwise), `origin`, `url`, and `appKey` are set when given,
226
+ * `retired` is cleared, and `lastSeen` moves to `now`. `firstSeen` is set
227
+ * only on create, and `label` is never touched. A zero-grant consent writes
228
+ * too, so an App Connect app with no grants is indexed by its key.
229
+ *
230
+ * Refuses an entry of another kind with {@link ConnectionKindMismatchError},
231
+ * and a grant delegated to another party or targeting another Space with a
232
+ * `TypeError`, before anything is written.
233
+ *
234
+ * @param options {object}
235
+ * @param options.store {ConnectionsStore}
236
+ * @param options.hmacKey {ConnectionIdKey}
237
+ * @param options.did {string} the party's DID, every grant's controller
238
+ * @param options.kind {ConnectionKind} the kind this flow writes
239
+ * @param options.spaceUrl {string} this Space's container URL, every
240
+ * grant's target prefix
241
+ * @param options.grants {Array<object>} `{ zcap, grantKind }` per grant
242
+ * @param [options.name] {string} the party's self-declared name
243
+ * @param [options.origin] {string} the attested Web origin (App Connect)
244
+ * @param [options.url] {string} the canonical app URL (App Connect)
245
+ * @param [options.appKey] {string} the app-key Resource id (App Connect)
246
+ * @param [options.now] {Date}
247
+ * @returns {Promise<ConnectionWriteResult>}
248
+ */
249
+ export async function recordGrants({ store, hmacKey, did, kind, spaceUrl, grants, name, origin, url, appKey, now = new Date() }) {
250
+ const stamp = now.toISOString();
251
+ const recorded = [];
252
+ const seen = new Set();
253
+ for (const grant of grants) {
254
+ const zcap = checkedGrant({ did, spaceUrl, grant });
255
+ if (!seen.has(zcap.id)) {
256
+ seen.add(zcap.id);
257
+ recorded.push({ zcap, grantKind: grant.grantKind, grantedAt: stamp });
258
+ }
259
+ }
260
+ const normalizedName = name === undefined ? undefined : normalizeDisplayName({ value: name });
261
+ const declared = {
262
+ ...(normalizedName !== undefined && { name: normalizedName }),
263
+ ...(origin !== undefined && { origin }),
264
+ ...(url !== undefined && { url }),
265
+ ...(appKey !== undefined && { appKey })
266
+ };
267
+ return writePartyConnection({
268
+ store,
269
+ hmacKey,
270
+ did,
271
+ change(current) {
272
+ if (current === undefined) {
273
+ return {
274
+ body: {
275
+ ...newConnectionEntry({ kind, did, now }),
276
+ ...declared,
277
+ grants: recorded
278
+ }
279
+ };
280
+ }
281
+ assertKind({ entry: current.entry, kind });
282
+ const held = new Set(current.entry.grants.map(grant => grant.zcap.id));
283
+ const body = {
284
+ ...current.body,
285
+ ...declared,
286
+ lastSeen: stamp,
287
+ grants: [
288
+ ...current.entry.grants,
289
+ ...recorded.filter(grant => !held.has(grant.zcap.id))
290
+ ]
291
+ };
292
+ delete body.retired;
293
+ return { body };
294
+ }
295
+ });
296
+ }
297
+ /**
298
+ * Removes grants from the party's entry by capability id, whatever the
299
+ * entry's kind. Used by an unshare after its revocation, and by a torn
300
+ * consent's rollback. An absent entry, or one holding none of the ids,
301
+ * writes nothing.
302
+ *
303
+ * @param options {object}
304
+ * @param options.store {ConnectionsStore}
305
+ * @param options.hmacKey {ConnectionIdKey}
306
+ * @param options.did {string} the party's DID
307
+ * @param options.zcapIds {Iterable<string>} the capability ids to remove
308
+ * @returns {Promise<ConnectionWriteResult>}
309
+ */
310
+ export async function removeGrants({ store, hmacKey, did, zcapIds }) {
311
+ const removing = new Set(zcapIds);
312
+ return writePartyConnection({
313
+ store,
314
+ hmacKey,
315
+ did,
316
+ change(current) {
317
+ if (current === undefined) {
318
+ return { stop: 'absent' };
319
+ }
320
+ const kept = current.entry.grants.filter(grant => !removing.has(grant.zcap.id));
321
+ if (kept.length === current.entry.grants.length) {
322
+ return { stop: 'unchanged' };
323
+ }
324
+ return { body: { ...current.body, grants: kept } };
325
+ }
326
+ });
327
+ }
328
+ /**
329
+ * Retires the party's entry, of any kind, once a revocation has handled its
330
+ * grants: empties `grants`, drops `appKey`, and stamps `retired`. `name`,
331
+ * `label`, `origin`, `url`, `firstSeen`, `lastSeen`, and `writers` stay, so a
332
+ * departed party keeps resolving. An entry already retired with nothing left
333
+ * to empty writes nothing, and an absent entry writes nothing.
334
+ *
335
+ * Throws when a read finds a grant that passes the reader checks and is not
336
+ * among `handledZcapIds`: a concurrent consent merged it, and the revocation
337
+ * must run again before the entry may retire. A grant that fails the reader
338
+ * checks (another party's controller, a target outside this Space) is not
339
+ * the party's, and the retirement empties it with the rest.
340
+ *
341
+ * @param options {object}
342
+ * @param options.store {ConnectionsStore}
343
+ * @param options.hmacKey {ConnectionIdKey}
344
+ * @param options.did {string} the party's DID
345
+ * @param options.handledZcapIds {Iterable<string>} the capability ids the
346
+ * revocation POSTed
347
+ * @param options.spaceUrl {string} this Space's container URL
348
+ * @param [options.now] {Date}
349
+ * @returns {Promise<ConnectionWriteResult>}
350
+ */
351
+ export async function retireConnection({ store, hmacKey, did, handledZcapIds, spaceUrl, now = new Date() }) {
352
+ const handled = new Set(handledZcapIds);
353
+ return writePartyConnection({
354
+ store,
355
+ hmacKey,
356
+ did,
357
+ change(current) {
358
+ if (current === undefined) {
359
+ return { stop: 'absent' };
360
+ }
361
+ const unhandled = connectionGrants({
362
+ entry: current.entry,
363
+ spaceUrl
364
+ }).filter(grant => !handled.has(grant.zcapId));
365
+ if (unhandled.length > 0) {
366
+ throw new Error(`The connections entry carries ${unhandled.length} grant(s) this ` +
367
+ 'revocation did not handle (a consent merged them since); the ' +
368
+ 'revocation must run again before the entry retires.');
369
+ }
370
+ const { entry } = current;
371
+ if (entry.retired !== undefined &&
372
+ entry.grants.length === 0 &&
373
+ entry.appKey === undefined) {
374
+ return { stop: 'unchanged' };
375
+ }
376
+ const body = {
377
+ ...current.body,
378
+ grants: [],
379
+ retired: entry.retired ?? now.toISOString()
380
+ };
381
+ delete body.appKey;
382
+ return { body };
383
+ }
384
+ });
385
+ }
386
+ /**
387
+ * Sets the user's `label` on the party's entry, and its `name` when given.
388
+ * A blank `label` removes the member; an omitted one leaves it, and one
389
+ * outside the display-name rule is refused with a `TypeError`, since the
390
+ * user typed it and can shorten it. A `name` outside the rule is ignored. The enrollment approval writes
391
+ * the code's suggested label as `name` and passes `label` only when the
392
+ * approver edited it.
393
+ *
394
+ * Creates an absent entry only for a wallet client the verified account
395
+ * document lists (`kind: 'wallet-client'`, its did:key's signing-key
396
+ * multibase in `enrolledSigningKeys`), and throws for any other absent
397
+ * party. Refuses an entry of another kind with
398
+ * {@link ConnectionKindMismatchError}.
399
+ *
400
+ * @param options {object}
401
+ * @param options.store {ConnectionsStore}
402
+ * @param options.hmacKey {ConnectionIdKey}
403
+ * @param options.did {string} the party's DID
404
+ * @param options.kind {ConnectionKind} the kind the calling surface lists
405
+ * the party as
406
+ * @param [options.label] {string} the user's name for the party
407
+ * @param [options.name] {string} the party's name (a client's default
408
+ * platform label, or an enrollee's suggested label)
409
+ * @param [options.enrolledSigningKeys] {ReadonlySet<string>} the enrolled
410
+ * clients' signing-key multibases in the verified account document; needed
411
+ * to create a wallet client's entry
412
+ * @param [options.now] {Date}
413
+ * @returns {Promise<ConnectionWriteResult>}
414
+ */
415
+ export async function setConnectionLabel({ store, hmacKey, did, kind, label, name, enrolledSigningKeys, now = new Date() }) {
416
+ const trimmedLabel = label?.trim();
417
+ const normalizedLabel = trimmedLabel
418
+ ? normalizeDisplayName({ value: trimmedLabel })
419
+ : undefined;
420
+ if (trimmedLabel && normalizedLabel === undefined) {
421
+ throw new TypeError('A label is 1 to 64 code points once control and bidi characters are ' +
422
+ 'stripped.');
423
+ }
424
+ const normalizedName = name === undefined ? undefined : normalizeDisplayName({ value: name });
425
+ return writePartyConnection({
426
+ store,
427
+ hmacKey,
428
+ did,
429
+ change(current) {
430
+ if (current === undefined) {
431
+ const multibase = signingKeyMultibaseOfDid({ did });
432
+ if (kind !== 'wallet-client' ||
433
+ multibase === undefined ||
434
+ enrolledSigningKeys?.has(multibase) !== true) {
435
+ throw new Error('No connections entry stands for this party, and one is created ' +
436
+ 'here only for a wallet client the verified account document ' +
437
+ 'lists.');
438
+ }
439
+ return {
440
+ body: {
441
+ ...newConnectionEntry({ kind, did, now }),
442
+ ...(normalizedName !== undefined && { name: normalizedName }),
443
+ ...(normalizedLabel !== undefined && { label: normalizedLabel })
444
+ }
445
+ };
446
+ }
447
+ assertKind({ entry: current.entry, kind });
448
+ const body = { ...current.body };
449
+ if (trimmedLabel !== undefined) {
450
+ if (normalizedLabel !== undefined) {
451
+ body.label = normalizedLabel;
452
+ }
453
+ else {
454
+ delete body.label;
455
+ }
456
+ }
457
+ if (normalizedName !== undefined) {
458
+ body.name = normalizedName;
459
+ }
460
+ if (body.label === current.body.label &&
461
+ body.name === current.body.name) {
462
+ return { stop: 'unchanged' };
463
+ }
464
+ return { body };
465
+ }
466
+ });
467
+ }
468
+ //# sourceMappingURL=upsert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upsert.js","sourceRoot":"","sources":["../../src/connections/upsert.ts"],"names":[],"mappings":"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"}