memeloop 0.2.0 → 0.2.2

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 (42) hide show
  1. package/dist/browser.cjs +1 -1
  2. package/dist/browser.cjs.map +1 -1
  3. package/dist/browser.d.cts +5 -5
  4. package/dist/browser.d.ts +5 -5
  5. package/dist/browser.js +1 -1
  6. package/dist/chunk-JRCEXHTP.js +1 -0
  7. package/dist/{chunk-ECNKBH5A.js → chunk-KXVZQLJL.js} +127 -21
  8. package/dist/chunk-KXVZQLJL.js.map +1 -0
  9. package/dist/{chunk-CCEFAOSH.js → chunk-WHXFUMDE.js} +2 -2
  10. package/dist/{chunk-CCEFAOSH.js.map → chunk-WHXFUMDE.js.map} +1 -1
  11. package/dist/device-network-portable.cjs +132 -20
  12. package/dist/device-network-portable.cjs.map +1 -1
  13. package/dist/device-network-portable.d.cts +3 -3
  14. package/dist/device-network-portable.d.ts +3 -3
  15. package/dist/device-network-portable.js +14 -2
  16. package/dist/device-network.cjs +132 -20
  17. package/dist/device-network.cjs.map +1 -1
  18. package/dist/device-network.d.cts +2 -2
  19. package/dist/device-network.d.ts +2 -2
  20. package/dist/device-network.js +14 -2
  21. package/dist/index.cjs +134 -22
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +4 -4
  24. package/dist/index.d.ts +4 -4
  25. package/dist/index.js +15 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/loop-api.cjs.map +1 -1
  28. package/dist/{orchestration-portable-BbkwLbC9.d.ts → orchestration-portable-B4udCSVd.d.ts} +1 -1
  29. package/dist/{orchestration-portable-DNKzAtNq.d.cts → orchestration-portable-BWaCsCGK.d.cts} +1 -1
  30. package/dist/orchestration-portable.cjs +1 -1
  31. package/dist/orchestration-portable.cjs.map +1 -1
  32. package/dist/orchestration-portable.d.cts +2 -2
  33. package/dist/orchestration-portable.d.ts +2 -2
  34. package/dist/orchestration-portable.js +1 -1
  35. package/dist/{pairingInvite-DDx_-IAp.d.cts → pairingInvite-C12n-7Ak.d.cts} +15 -3
  36. package/dist/{pairingInvite-Dkz8CLsb.d.ts → pairingInvite-CPQkuhLQ.d.ts} +15 -3
  37. package/dist/{remoteClient-BKmQEQY9.d.cts → remoteClient-DFIyCZEv.d.cts} +1 -1
  38. package/dist/{remoteClient-D5hco6cS.d.ts → remoteClient-DwBCoHpc.d.ts} +1 -1
  39. package/package.json +1 -1
  40. package/dist/chunk-ECNKBH5A.js.map +0 -1
  41. package/dist/chunk-MXRXYGWW.js +0 -1
  42. /package/dist/{chunk-MXRXYGWW.js.map → chunk-JRCEXHTP.js.map} +0 -0
@@ -21,9 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var device_network_entry_exports = {};
22
22
  __export(device_network_entry_exports, {
23
23
  ChatSyncEngine: () => ChatSyncEngine,
24
+ DEVICE_BINDING_SIGNATURE_DOMAIN: () => DEVICE_BINDING_SIGNATURE_DOMAIN,
25
+ DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN: () => DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN,
24
26
  DEVICE_ORCHESTRATION_PROTOCOL: () => DEVICE_ORCHESTRATION_PROTOCOL,
25
27
  DEVICE_PAIRING_INVITE_PROTOCOL: () => DEVICE_PAIRING_INVITE_PROTOCOL,
26
28
  DEVICE_PAIRING_INVITE_TTL_MS: () => DEVICE_PAIRING_INVITE_TTL_MS,
29
+ DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN: () => DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN,
27
30
  DeviceCloudConnectionCoordinator: () => DeviceCloudConnectionCoordinator,
28
31
  JsonFrameError: () => JsonFrameError,
29
32
  LIBP2P_RPC_REQUEST_TYPE: () => LIBP2P_RPC_REQUEST_TYPE,
@@ -36,6 +39,9 @@ __export(device_network_entry_exports, {
36
39
  MemoryDeviceSyncStateStore: () => MemoryDeviceSyncStateStore,
37
40
  PeerNodeSyncAdapter: () => PeerNodeSyncAdapter,
38
41
  attachmentBlobFromWire: () => attachmentBlobFromWire,
42
+ buildDeviceBindingMessage: () => buildDeviceBindingMessage,
43
+ buildDeviceConnectionGrantMessage: () => buildDeviceConnectionGrantMessage,
44
+ buildDeviceRelayReservationTokenMessage: () => buildDeviceRelayReservationTokenMessage,
39
45
  canonicalDevicePairingInviteBytes: () => canonicalDevicePairingInviteBytes,
40
46
  computeMissingVersionRanges: () => computeMissingVersionRanges,
41
47
  createDeviceOrchestrationStreamHandler: () => createDeviceOrchestrationStreamHandler,
@@ -124,8 +130,12 @@ var DeviceCloudConnectionCoordinator = class {
124
130
  async stop() {
125
131
  this.started = false;
126
132
  this.clearTimer();
127
- this.controller.abort(new Error("device cloud coordinator stopped"));
133
+ const stoppedController = this.controller;
134
+ stoppedController.abort(new Error("device cloud coordinator stopped"));
128
135
  await this.inFlight?.catch(() => void 0);
136
+ if (this.controller === stoppedController) {
137
+ this.controller = new AbortController();
138
+ }
129
139
  }
130
140
  async setConfiguration(configuration) {
131
141
  this.configuration = configuration;
@@ -274,6 +284,43 @@ var DeviceCloudConnectionCoordinator = class {
274
284
  }
275
285
  };
276
286
 
287
+ // src/device-network/deviceGrantMessages.ts
288
+ var DEVICE_BINDING_SIGNATURE_DOMAIN = "memeloop-device-binding-v2";
289
+ var DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN = "memeloop-device-connection-grant-v2";
290
+ var DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN = "memeloop-device-relay-admission-v2";
291
+ function buildDeviceBindingMessage(input) {
292
+ return new TextEncoder().encode([
293
+ DEVICE_BINDING_SIGNATURE_DOMAIN,
294
+ `accountId=${input.accountId}`,
295
+ `peerId=${input.peerId}`,
296
+ `publicKey=${input.publicKeyMultibase}`,
297
+ `nonce=${input.nonce}`
298
+ ].join("\n"));
299
+ }
300
+ function buildDeviceConnectionGrantMessage(grant) {
301
+ return new TextEncoder().encode([
302
+ DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN,
303
+ `issuer=${grant.issuer}`,
304
+ `accountId=${grant.accountId}`,
305
+ `subjectPeerId=${grant.subjectPeerId}`,
306
+ `allowedPeerIds=${grant.allowedPeerIds.join(",")}`,
307
+ `issuedAt=${grant.issuedAt}`,
308
+ `expiresAt=${grant.expiresAt}`
309
+ ].join("\n"));
310
+ }
311
+ function buildDeviceRelayReservationTokenMessage(token) {
312
+ return new TextEncoder().encode([
313
+ DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN,
314
+ `issuer=${token.issuer}`,
315
+ `accountId=${token.accountId}`,
316
+ `peerId=${token.peerId}`,
317
+ `relayMultiaddrs=${token.relayMultiaddrs.join(",")}`,
318
+ `bootstrapMultiaddrs=${token.bootstrapMultiaddrs.join(",")}`,
319
+ `issuedAt=${token.issuedAt}`,
320
+ `expiresAt=${token.expiresAt}`
321
+ ].join("\n"));
322
+ }
323
+
277
324
  // src/orchestration/errors.ts
278
325
  var OrchestrationError = class extends Error {
279
326
  code;
@@ -696,39 +743,92 @@ async function readSingleRequest(stream, maxFrameBytes) {
696
743
  }
697
744
  async function* withWatchBookmarks(source, request, signal) {
698
745
  const iterator = source[Symbol.asyncIterator]();
699
- let pending = iterator.next();
746
+ let activity;
747
+ let activityWaiter;
748
+ let bookmarkTimer;
749
+ let readInFlight = false;
750
+ let lastResourceVersion = watchResourceVersion(request.payload.options) ?? "0";
751
+ const clearBookmarkTimer = () => {
752
+ if (bookmarkTimer !== void 0) clearTimeout(bookmarkTimer);
753
+ bookmarkTimer = void 0;
754
+ };
755
+ const publishActivity = (value) => {
756
+ if (activityWaiter) {
757
+ const resolve = activityWaiter;
758
+ activityWaiter = void 0;
759
+ clearBookmarkTimer();
760
+ resolve(value);
761
+ return;
762
+ }
763
+ activity = value;
764
+ };
765
+ const readNext = () => {
766
+ if (readInFlight) return;
767
+ readInFlight = true;
768
+ void iterator.next().then(
769
+ (value) => {
770
+ readInFlight = false;
771
+ publishActivity({ kind: "value", value });
772
+ },
773
+ (error) => {
774
+ readInFlight = false;
775
+ publishActivity({ kind: "error", error });
776
+ }
777
+ );
778
+ };
779
+ const waitForActivity = () => {
780
+ if (activity) {
781
+ const value = activity;
782
+ activity = void 0;
783
+ return Promise.resolve(value);
784
+ }
785
+ if (signal.aborted) return Promise.resolve({ kind: "aborted" });
786
+ return new Promise((resolve) => {
787
+ activityWaiter = resolve;
788
+ bookmarkTimer = setTimeout(() => {
789
+ bookmarkTimer = void 0;
790
+ activityWaiter = void 0;
791
+ resolve({ kind: "bookmark" });
792
+ }, WATCH_BOOKMARK_INTERVAL_MS);
793
+ });
794
+ };
795
+ const onAbort = () => {
796
+ publishActivity({ kind: "aborted" });
797
+ };
798
+ signal.addEventListener("abort", onAbort, { once: true });
799
+ readNext();
700
800
  try {
701
801
  for (; ; ) {
702
- const result = await Promise.race([
703
- pending.then((value) => ({ kind: "value", value })),
704
- new Promise((resolve) => {
705
- const timer = setTimeout(() => {
706
- resolve({ kind: "bookmark" });
707
- }, WATCH_BOOKMARK_INTERVAL_MS);
708
- signal.addEventListener("abort", () => {
709
- clearTimeout(timer);
710
- resolve({ kind: "bookmark" });
711
- }, { once: true });
712
- })
713
- ]);
714
- if (signal.aborted) return;
802
+ const result = await waitForActivity();
803
+ if (result.kind === "aborted") return;
715
804
  if (result.kind === "bookmark") {
716
805
  yield {
717
806
  protocol: request.protocol,
718
807
  requestId: request.requestId,
719
808
  ok: true,
720
- result: { type: "BOOKMARK", resourceVersion: String(Date.now()) }
809
+ result: { type: "BOOKMARK", resourceVersion: lastResourceVersion }
721
810
  };
722
811
  continue;
723
812
  }
813
+ if (result.kind === "error") throw result.error;
724
814
  if (result.value.done) return;
725
- yield result.value.value;
726
- pending = iterator.next();
815
+ const response = result.value.value;
816
+ lastResourceVersion = response.ok ? watchResourceVersion(response.result) ?? lastResourceVersion : lastResourceVersion;
817
+ yield response;
818
+ readNext();
727
819
  }
728
820
  } finally {
821
+ clearBookmarkTimer();
822
+ activityWaiter = void 0;
823
+ signal.removeEventListener("abort", onAbort);
729
824
  void iterator.return?.();
730
825
  }
731
826
  }
827
+ function watchResourceVersion(value) {
828
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
829
+ const resourceVersion = value.resourceVersion;
830
+ return typeof resourceVersion === "string" && resourceVersion.length > 0 ? resourceVersion : void 0;
831
+ }
732
832
  function createDeviceOrchestrationStreamHandler(options) {
733
833
  const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;
734
834
  assertFrameLimit(maxFrameBytes);
@@ -850,6 +950,12 @@ var Libp2pDeviceSyncTransport = class {
850
950
  async request(peerId, method, parameters) {
851
951
  const grant = await this.grantProvider?.(peerId);
852
952
  const stream = await this.deviceNetwork.openStream(peerId, "/memeloop/sync/2.0.0", grant);
953
+ let aborted = false;
954
+ const abort = async (error) => {
955
+ if (aborted) return;
956
+ aborted = true;
957
+ await stream.abort(error);
958
+ };
853
959
  const request = {
854
960
  type: LIBP2P_SYNC_REQUEST_TYPE,
855
961
  id: crypto.randomUUID(),
@@ -864,7 +970,7 @@ var Libp2pDeviceSyncTransport = class {
864
970
  maxPayloadBytes: 16 * 1024 * 1024,
865
971
  idleTimeoutMs: 15e3,
866
972
  totalTimeoutMs: 12e4,
867
- abort: async (error) => stream.abort(error)
973
+ abort
868
974
  })) {
869
975
  if (response !== void 0) throw new Error("sync_response_multiple");
870
976
  response = value;
@@ -874,7 +980,7 @@ var Libp2pDeviceSyncTransport = class {
874
980
  if (!response.ok) throw new Error(response.error);
875
981
  return response.result;
876
982
  } catch (error) {
877
- if (error instanceof JsonFrameError) await stream.abort(error);
983
+ if (error instanceof JsonFrameError) await abort(error);
878
984
  throw error;
879
985
  } finally {
880
986
  await stream.close().catch(() => void 0);
@@ -1492,9 +1598,12 @@ function sameTrustedDevice(left, right) {
1492
1598
  // Annotate the CommonJS export names for ESM import in node:
1493
1599
  0 && (module.exports = {
1494
1600
  ChatSyncEngine,
1601
+ DEVICE_BINDING_SIGNATURE_DOMAIN,
1602
+ DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN,
1495
1603
  DEVICE_ORCHESTRATION_PROTOCOL,
1496
1604
  DEVICE_PAIRING_INVITE_PROTOCOL,
1497
1605
  DEVICE_PAIRING_INVITE_TTL_MS,
1606
+ DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN,
1498
1607
  DeviceCloudConnectionCoordinator,
1499
1608
  JsonFrameError,
1500
1609
  LIBP2P_RPC_REQUEST_TYPE,
@@ -1507,6 +1616,9 @@ function sameTrustedDevice(left, right) {
1507
1616
  MemoryDeviceSyncStateStore,
1508
1617
  PeerNodeSyncAdapter,
1509
1618
  attachmentBlobFromWire,
1619
+ buildDeviceBindingMessage,
1620
+ buildDeviceConnectionGrantMessage,
1621
+ buildDeviceRelayReservationTokenMessage,
1510
1622
  canonicalDevicePairingInviteBytes,
1511
1623
  computeMissingVersionRanges,
1512
1624
  createDeviceOrchestrationStreamHandler,