@derec-alliance/react-native 0.0.4 → 0.0.6

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/lib/protocol.js CHANGED
@@ -3,7 +3,6 @@
3
3
  // Copyright (c) 2026 DeRec Alliance. All rights reserved.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.DeRecProtocol = exports.DeRecProtocolBuilder = void 0;
6
- exports.protocolDiscriminant = protocolDiscriminant;
7
6
  exports.buildProtectSecretParams = buildProtectSecretParams;
8
7
  exports.buildRestoreParams = buildRestoreParams;
9
8
  const codec_1 = require("./codec");
@@ -50,24 +49,6 @@ function reviveEventBytes(value) {
50
49
  function decodeEvents(buffer) {
51
50
  return reviveEventBytes((0, codec_1.jsonFromBytes)(buffer));
52
51
  }
53
- /**
54
- * Maps a transport protocol name to the `derec_proto::Protocol` discriminant.
55
- * The shared enum fixture every other numeric mapping in this SDK is checked
56
- * against does not carry this enum (it
57
- * only covers the Rust-internal serde enums listed under its `"enums"` key);
58
- * the transport `Protocol` enum lives in `protobufs/transportprotocol.proto`
59
- * instead, where `HTTPS = 0` and `GRPC = 1` are defined.
60
- */
61
- function protocolDiscriminant(protocol) {
62
- switch (protocol.toLowerCase()) {
63
- case 'https':
64
- return 0;
65
- case 'grpc':
66
- return 1;
67
- default:
68
- throw new Error(`DeRec: unknown transport protocol "${protocol}"`);
69
- }
70
- }
71
52
  function encodeTarget(target) {
72
53
  if (target === null) {
73
54
  return null;
@@ -219,14 +200,8 @@ function buildStartParams(flowKind, params) {
219
200
  if (p.communication_info !== undefined) {
220
201
  out.communication_info = p.communication_info;
221
202
  }
222
- if (p.own_transports !== undefined && p.own_transports.length > 0) {
203
+ if (p.own_transports !== undefined) {
223
204
  out.own_transports = p.own_transports;
224
- // The first entry also fills the deprecated singular field so a peer
225
- // predating `supported_transports` still learns the new address.
226
- out.transport_protocol = p.own_transports[0];
227
- }
228
- else if (p.transport_protocol !== undefined) {
229
- out.transport_protocol = p.transport_protocol;
230
205
  }
231
206
  return (0, codec_1.jsonToBytes)(out);
232
207
  }
@@ -296,22 +271,10 @@ class DeRecProtocolBuilder {
296
271
  this.stores.transport = transport;
297
272
  return this;
298
273
  }
299
- /**
300
- * @deprecated Use {@link withOwnTransports}, which takes the whole
301
- * preference list — `withOwnTransports([endpoint])` is the direct
302
- * replacement. Removed at 0.0.5.
303
- */
304
- withOwnTransport(endpoint) {
305
- this.config.own_transport_uri = endpoint.uri;
306
- this.config.own_transport_protocol = protocolDiscriminant(endpoint.protocol);
307
- return this;
308
- }
309
274
  /**
310
275
  * Set every transport endpoint this application serves, in preference
311
- * order. Written to the config's `own_transports` array, which takes
312
- * precedence over `own_transport_uri` / `own_transport_protocol` on the
313
- * Rust side when non-empty — see `ProtocolConfig` in
314
- * `library/src/interop/ffi/protocol/handle/mod.rs`.
276
+ * order. Written to the config's `own_transports` array — see
277
+ * `ProtocolConfig` in `library/src/interop/ffi/protocol/handle/mod.rs`.
315
278
  *
316
279
  * The order given is forwarded verbatim: it is not sorted, deduplicated,
317
280
  * or reordered here. It is this application's own preference and
@@ -320,15 +283,11 @@ class DeRecProtocolBuilder {
320
283
  * listing an endpoint this application does not serve makes pairing
321
284
  * succeed and replies vanish.
322
285
  *
323
- * Supersedes {@link withOwnTransport} for applications serving more
324
- * than one transport; the single-endpoint setter remains fully
325
- * supported.
286
+ * Required: `build()` with no own transport is refused by the library,
287
+ * since a node with no endpoint cannot be reached by any peer.
326
288
  */
327
289
  withOwnTransports(transports) {
328
- this.config.own_transports = transports.map((t) => ({
329
- uri: t.uri,
330
- protocol: protocolDiscriminant(t.protocol),
331
- }));
290
+ this.config.own_transports = transports.map(({ uri, protocol }) => ({ uri, protocol }));
332
291
  return this;
333
292
  }
334
293
  /** Default: 3. */
@@ -352,47 +311,20 @@ class DeRecProtocolBuilder {
352
311
  this.config.timeouts = { ...timeouts };
353
312
  return this;
354
313
  }
355
- /**
356
- * @deprecated Use {@link withUnsafeConnection}, which names both gated
357
- * schemes. Removed at 0.0.5. Default: false.
358
- */
359
- withUnsafeHttp(allow) {
360
- this.config.unsafe_http = allow;
361
- return this;
362
- }
363
314
  /**
364
315
  * Accept plaintext `http://` and `grpc://` transport endpoints.
365
- * **Development only.** Default: false. Supersedes
366
- * {@link withUnsafeHttp}, which names only the HTTP scheme.
367
- *
368
- * Either flag alone is honored. Setting both to disagreeing values fails
369
- * construction with the error code `CONFLICTING_PLAINTEXT_OPT_IN` rather
370
- * than resolving silently, because precedence would hand the decision to
371
- * the flag being removed.
316
+ * **Development only.** Default: false.
372
317
  */
373
318
  withUnsafeConnection(allow) {
374
319
  this.config.unsafe_connection = allow;
375
320
  return this;
376
321
  }
377
322
  /**
378
- * Default: empty. `derec_protocol_new`'s own `communication_info` argument
379
- * is a pre-encoded `CommunicationInfo` protobuf message, and this SDK has
380
- * no encoder for that message — the C ABI exposes one only for
381
- * `ContactMessage`. Hand-rolling one here would be SDK-side protocol logic
382
- * with no test coverage — exactly what this codebase's "Rust decides, the
383
- * SDK only marshals" rule forbids. Instead,
384
- * `build()` constructs the protocol with an empty `communication_info`
385
- * (a legitimate, always-accepted value — see `decode_communication_info`
386
- * in `library/src/interop/ffi/protocol/handle/mod.rs`, which treats a zero-length
387
- * buffer as "no entries") and then calls the already-bound
388
- * {@link DeRecProtocol.setCommunicationInfo}, which takes the same map as
389
- * plain JSON (`derec_protocol_set_communication_info` in
390
- * `library/src/interop/ffi/protocol/handle/config.rs`). That setter is queued on
391
- * the protocol's serial worker before `build()` returns, so it is ordered
392
- * ahead of every call the caller can subsequently make.
323
+ * Default: empty. Written to the config's `communication_info` key, so the
324
+ * map is part of the protocol from construction.
393
325
  */
394
326
  withCommunicationInfo(info) {
395
- this.communicationInfo = info;
327
+ this.config.communication_info = info;
396
328
  return this;
397
329
  }
398
330
  /** Default: false. */
@@ -402,15 +334,7 @@ class DeRecProtocolBuilder {
402
334
  }
403
335
  /** Default: "required". */
404
336
  withUnpairAck(ack) {
405
- if (ack === 'required') {
406
- this.config.unpair_ack = 0;
407
- }
408
- else if (ack === 'not_required') {
409
- this.config.unpair_ack = 1;
410
- }
411
- else {
412
- throw new Error(`DeRec: unknown unpair ack "${ack}"`);
413
- }
337
+ this.config.unpair_ack = ack;
414
338
  return this;
415
339
  }
416
340
  /** Default: false. */
@@ -418,17 +342,20 @@ class DeRecProtocolBuilder {
418
342
  this.config.auto_reply_to = enabled;
419
343
  return this;
420
344
  }
421
- /** Default: empty policy (every flow off). */
345
+ /**
346
+ * Default: empty policy (every flow off). A flow left out of `policy` is
347
+ * left out of the config, and the library applies its own default to it.
348
+ */
422
349
  withAutoAccept(policy) {
423
350
  this.config.auto_accept = {
424
- pairing: policy.pairing ?? false,
425
- pre_pair: policy.prePair ?? false,
426
- store_share: policy.storeShare ?? false,
427
- verify_share: policy.verifyShare ?? false,
428
- discovery: policy.discovery ?? false,
429
- get_share: policy.getShare ?? false,
430
- unpair: policy.unpair ?? false,
431
- update_channel_info: policy.updateChannelInfo ?? false,
351
+ pairing: policy.pairing,
352
+ pre_pair: policy.prePair,
353
+ store_share: policy.storeShare,
354
+ verify_share: policy.verifyShare,
355
+ discovery: policy.discovery,
356
+ get_share: policy.getShare,
357
+ unpair: policy.unpair,
358
+ update_channel_info: policy.updateChannelInfo,
432
359
  };
433
360
  return this;
434
361
  }
@@ -444,22 +371,24 @@ class DeRecProtocolBuilder {
444
371
  * against the peer's range on inbound ones: a range that fails to
445
372
  * intersect rejects the pairing. Every bound is optional and defaults to
446
373
  * `0`, which the protocol reads as "no constraint on this dimension".
374
+ * Bounds cross to the library as decimal strings, so the full `i64` range
375
+ * survives; a bound left out is left out of the config, and the library
376
+ * applies its default.
447
377
  *
448
378
  * Default: unset — no constraints advertised, every peer range accepted.
449
379
  */
450
380
  withParameterRange(range) {
451
- const n = (v) => Number(v ?? 0n);
452
381
  this.config.parameter_range = {
453
- min_share_size: n(range.min_share_size),
454
- max_share_size: n(range.max_share_size),
455
- min_time_between_verifications: n(range.min_time_between_verifications),
456
- max_time_between_verifications: n(range.max_time_between_verifications),
457
- min_time_between_share_updates: n(range.min_time_between_share_updates),
458
- max_time_between_share_updates: n(range.max_time_between_share_updates),
459
- min_unresponsive_deletion_timeout: n(range.min_unresponsive_deletion_timeout),
460
- max_unresponsive_deletion_timeout: n(range.max_unresponsive_deletion_timeout),
461
- min_unresponsive_deactivation_timeout: n(range.min_unresponsive_deactivation_timeout),
462
- max_unresponsive_deactivation_timeout: n(range.max_unresponsive_deactivation_timeout),
382
+ min_share_size: range.min_share_size?.toString(),
383
+ max_share_size: range.max_share_size?.toString(),
384
+ min_time_between_verifications: range.min_time_between_verifications?.toString(),
385
+ max_time_between_verifications: range.max_time_between_verifications?.toString(),
386
+ min_time_between_share_updates: range.min_time_between_share_updates?.toString(),
387
+ max_time_between_share_updates: range.max_time_between_share_updates?.toString(),
388
+ min_unresponsive_deletion_timeout: range.min_unresponsive_deletion_timeout?.toString(),
389
+ max_unresponsive_deletion_timeout: range.max_unresponsive_deletion_timeout?.toString(),
390
+ min_unresponsive_deactivation_timeout: range.min_unresponsive_deactivation_timeout?.toString(),
391
+ max_unresponsive_deactivation_timeout: range.max_unresponsive_deactivation_timeout?.toString(),
463
392
  };
464
393
  return this;
465
394
  }
@@ -467,34 +396,18 @@ class DeRecProtocolBuilder {
467
396
  const config = {
468
397
  secret_id: this.secretIdValue.toString(),
469
398
  replica_id: null,
470
- own_transport_uri: '',
471
- own_transport_protocol: 0,
472
399
  ...this.config,
473
400
  };
474
401
  const host = (0, native_1.getNative)().protocol_new(JSON.stringify(config), new Uint8Array(0), this.stores);
475
- const protocol = DeRecProtocol.fromHost(host);
476
- if (this.communicationInfo !== undefined) {
477
- // `setCommunicationInfo` is asynchronous, but `build()` stays
478
- // synchronous: the guarantee callers need is not that the map has been
479
- // applied by the time `build()` returns, it is that no flow can run
480
- // before it. Posting it here puts it on the protocol's serial worker
481
- // queue ahead of anything the caller has had the chance to start, so
482
- // every subsequent call observes it. Left unhandled deliberately — a
483
- // failure reaches the runtime's unhandled-rejection reporting rather
484
- // than being silently discarded, and `build()` has no synchronous
485
- // channel to raise it on.
486
- void protocol.setCommunicationInfo(this.communicationInfo);
487
- }
488
- return protocol;
402
+ return DeRecProtocol.fromHost(host);
489
403
  }
490
404
  }
491
405
  exports.DeRecProtocolBuilder = DeRecProtocolBuilder;
492
406
  /**
493
407
  * Thin wrapper around the `ProtocolHost` JSI host object, mirroring
494
408
  * `@derec-alliance/nodejs`'s `DeRecProtocol` — same methods, and the same
495
- * sync/async split except for `setCommunicationInfo` and `setOwnTransport`,
496
- * which return a `Promise` here (see their own doc comments for why);
497
- * `secretId` is synchronous and everything else returns a `Promise`. Every method encodes its
409
+ * sync/async split: `secretId` is synchronous and everything else returns a
410
+ * `Promise`. Every method encodes its
498
411
  * arguments into the wire shape the host function expects and decodes its
499
412
  * result back into the typed value declared here; no protocol decision is
500
413
  * made in this class.
@@ -519,60 +432,37 @@ class DeRecProtocol {
519
432
  return this.host.secretId();
520
433
  }
521
434
  /**
522
- * Returns a `Promise`, where `@derec-alliance/nodejs` declares this
523
- * `void`. The native setter takes the same handle mutex a running flow
524
- * holds across its store callbacks, so calling it on the JavaScript thread
525
- * would block that thread until the flow released the mutex — which it
526
- * cannot do while it is waiting on the JavaScript thread. The binding
527
- * therefore queues the setter onto the same serial worker every flow runs
528
- * on, which orders it after any call already in flight. The nodejs SDK is
529
- * WASM and single-threaded, so it has no such hazard.
435
+ * Replaces this node's local communication info.
530
436
  *
531
- * Callers that ignore the result behave exactly as before, so this stays
532
- * source-compatible with nodejs-shaped code; awaiting it additionally
533
- * surfaces a failure that would otherwise be swallowed.
437
+ * The native setter takes the same handle mutex a running flow holds
438
+ * across its store callbacks, so calling it on the JavaScript thread would
439
+ * block that thread until the flow released the mutex — which it cannot do
440
+ * while it is waiting on the JavaScript thread. The binding therefore
441
+ * queues the setter onto the same serial worker every flow runs on, which
442
+ * orders it after any call already in flight. Awaiting the returned
443
+ * `Promise` surfaces a failure that would otherwise be swallowed.
534
444
  */
535
445
  setCommunicationInfo(info) {
536
446
  return this.host.setCommunicationInfo((0, codec_1.jsonToBytes)(info));
537
447
  }
538
- /**
539
- * Replace this node's endpoint for one protocol, leaving the others
540
- * alone. A node serves at most one endpoint per protocol, so the
541
- * `(uri, protocol)` pair identifies the entry it replaces; an entry for a
542
- * protocol not yet served is appended, and a replaced one keeps its
543
- * position in the preference order.
544
- *
545
- * Returns a `Promise` for the same reason {@link setCommunicationInfo} does.
546
- *
547
- * @deprecated Use {@link setOwnTransports}, which takes the whole
548
- * preference list and is the only way to change which protocols this node
549
- * serves, or their order. Removed at 0.0.5.
550
- */
551
- setOwnTransport(uri, protocol) {
552
- return this.host.setOwnTransport(uri, protocolDiscriminant(protocol));
553
- }
554
448
  /**
555
449
  * Replaces every endpoint this node advertises, in preference order —
556
- * the runtime counterpart to `withOwnTransports`, and the only way to
557
- * change a multi-endpoint node's set ({@link setOwnTransport} collapses
558
- * it to the one endpoint it is given).
450
+ * the runtime counterpart to `withOwnTransports`.
559
451
  *
560
452
  * Every entry is validated before any is stored, so a malformed URI
561
453
  * leaves the previous set intact. An empty array is rejected.
562
454
  *
563
- * Returns a `Promise` for the same reason {@link setCommunicationInfo} does.
455
+ * Queued onto the serial worker for the same reason as
456
+ * {@link setCommunicationInfo}.
564
457
  */
565
458
  setOwnTransports(transports) {
566
- const wire = transports.map(({ uri, protocol }) => ({
567
- uri,
568
- protocol: protocolDiscriminant(protocol),
569
- }));
459
+ const wire = transports.map(({ uri, protocol }) => ({ uri, protocol }));
570
460
  return this.host.setOwnTransports((0, codec_1.jsonToBytes)(wire));
571
461
  }
572
462
  /**
573
463
  * Decodes the `contact_wire_bytes` `derec_protocol_create_contact`
574
464
  * produces into a typed `ContactMessage`, so an application can read the
575
- * contact's `nonce`, `transport_protocol` and mode without a protobuf
465
+ * contact's `nonce`, `supported_transports` and mode without a protobuf
576
466
  * codec of its own. Feed the returned object straight back into
577
467
  * `start(FlowKind.Pairing, { contact })`, which re-encodes it.
578
468
  */
@@ -612,6 +502,21 @@ class DeRecProtocol {
612
502
  const buffer = (await this.host.removeExpiredChannels(olderThanSecs));
613
503
  return (0, codec_1.jsonFromBytes)(buffer);
614
504
  }
505
+ /**
506
+ * Rebuild this protocol's `secret_id` namespace from a recovered `Secret`.
507
+ * Pass the `secret` carried by the `SecretRecovered` event verbatim.
508
+ * A helper or member whose `transports` is empty gets no channel: it is
509
+ * reported as a `PeerNotRestored` event in the returned array and the rest
510
+ * of the roster is restored.
511
+ *
512
+ * Rejects with a `DeRecError`; among its codes:
513
+ *
514
+ * | code | meaning |
515
+ * |--------------------|-------------------------------------------------------------|
516
+ * | `already_restored` | A user-secret snapshot already exists for this `secret_id`. |
517
+ * | `restore_conflict` | Channels live at ids restore is about to write. The error |
518
+ * | | carries `channel_ids: string[]` listing the collisions. |
519
+ */
615
520
  async restore(recoveredSecret, version) {
616
521
  const params = buildRestoreParams(recoveredSecret, version);
617
522
  const buffer = (await this.host.restore((0, codec_1.jsonToBytes)(params)));
@@ -621,5 +526,9 @@ class DeRecProtocol {
621
526
  free() {
622
527
  this.host.free();
623
528
  }
529
+ /** Same as {@link DeRecProtocol.free}, for `using`. */
530
+ [Symbol.dispose]() {
531
+ this.free();
532
+ }
624
533
  }
625
534
  exports.DeRecProtocol = DeRecProtocol;