@meshline/sdk 0.0.0-stage → 0.1.0-alpha.1

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 (338) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -2
  3. package/dist/channels/repository.d.ts +73 -0
  4. package/dist/channels/repository.d.ts.map +1 -0
  5. package/dist/channels/repository.js +367 -0
  6. package/dist/channels/repository.js.map +1 -0
  7. package/dist/client/account-operations.d.ts +41 -0
  8. package/dist/client/account-operations.d.ts.map +1 -0
  9. package/dist/client/account-operations.js +304 -0
  10. package/dist/client/account-operations.js.map +1 -0
  11. package/dist/client/conversations.d.ts +36 -0
  12. package/dist/client/conversations.d.ts.map +1 -0
  13. package/dist/client/conversations.js +144 -0
  14. package/dist/client/conversations.js.map +1 -0
  15. package/dist/client.d.ts +53 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +162 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/components/account.d.ts +38 -0
  20. package/dist/components/account.d.ts.map +1 -0
  21. package/dist/components/account.js +243 -0
  22. package/dist/components/account.js.map +1 -0
  23. package/dist/components/channel.d.ts +78 -0
  24. package/dist/components/channel.d.ts.map +1 -0
  25. package/dist/components/channel.js +475 -0
  26. package/dist/components/channel.js.map +1 -0
  27. package/dist/components/component.d.ts +49 -0
  28. package/dist/components/component.d.ts.map +1 -0
  29. package/dist/components/component.js +194 -0
  30. package/dist/components/component.js.map +1 -0
  31. package/dist/components/device.d.ts +60 -0
  32. package/dist/components/device.d.ts.map +1 -0
  33. package/dist/components/device.js +648 -0
  34. package/dist/components/device.js.map +1 -0
  35. package/dist/components/group.d.ts +141 -0
  36. package/dist/components/group.d.ts.map +1 -0
  37. package/dist/components/group.js +933 -0
  38. package/dist/components/group.js.map +1 -0
  39. package/dist/components/message.d.ts +63 -0
  40. package/dist/components/message.d.ts.map +1 -0
  41. package/dist/components/message.js +439 -0
  42. package/dist/components/message.js.map +1 -0
  43. package/dist/components/profile.d.ts +37 -0
  44. package/dist/components/profile.d.ts.map +1 -0
  45. package/dist/components/profile.js +232 -0
  46. package/dist/components/profile.js.map +1 -0
  47. package/dist/crypto/groups.d.ts +56 -0
  48. package/dist/crypto/groups.d.ts.map +1 -0
  49. package/dist/crypto/groups.js +163 -0
  50. package/dist/crypto/groups.js.map +1 -0
  51. package/dist/crypto/messages.d.ts +52 -0
  52. package/dist/crypto/messages.d.ts.map +1 -0
  53. package/dist/crypto/messages.js +180 -0
  54. package/dist/crypto/messages.js.map +1 -0
  55. package/dist/crypto/primitives.d.ts +30 -0
  56. package/dist/crypto/primitives.d.ts.map +1 -0
  57. package/dist/crypto/primitives.js +102 -0
  58. package/dist/crypto/primitives.js.map +1 -0
  59. package/dist/errors.d.ts +11 -0
  60. package/dist/errors.d.ts.map +1 -0
  61. package/dist/errors.js +14 -0
  62. package/dist/errors.js.map +1 -0
  63. package/dist/groups/account-sync.d.ts +28 -0
  64. package/dist/groups/account-sync.d.ts.map +1 -0
  65. package/dist/groups/account-sync.js +235 -0
  66. package/dist/groups/account-sync.js.map +1 -0
  67. package/dist/groups/messages.d.ts +39 -0
  68. package/dist/groups/messages.d.ts.map +1 -0
  69. package/dist/groups/messages.js +141 -0
  70. package/dist/groups/messages.js.map +1 -0
  71. package/dist/groups/operations.d.ts +57 -0
  72. package/dist/groups/operations.d.ts.map +1 -0
  73. package/dist/groups/operations.js +225 -0
  74. package/dist/groups/operations.js.map +1 -0
  75. package/dist/groups/repository.d.ts +56 -0
  76. package/dist/groups/repository.d.ts.map +1 -0
  77. package/dist/groups/repository.js +254 -0
  78. package/dist/groups/repository.js.map +1 -0
  79. package/dist/groups/secrets.d.ts +67 -0
  80. package/dist/groups/secrets.d.ts.map +1 -0
  81. package/dist/groups/secrets.js +452 -0
  82. package/dist/groups/secrets.js.map +1 -0
  83. package/dist/groups/state.d.ts +39 -0
  84. package/dist/groups/state.d.ts.map +1 -0
  85. package/dist/groups/state.js +201 -0
  86. package/dist/groups/state.js.map +1 -0
  87. package/dist/identity/identifiers.d.ts +9 -0
  88. package/dist/identity/identifiers.d.ts.map +1 -0
  89. package/dist/identity/identifiers.js +37 -0
  90. package/dist/identity/identifiers.js.map +1 -0
  91. package/dist/identity/neo.d.ts +11 -0
  92. package/dist/identity/neo.d.ts.map +1 -0
  93. package/dist/identity/neo.js +77 -0
  94. package/dist/identity/neo.js.map +1 -0
  95. package/dist/index.d.ts +53 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +46 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/interactions.d.ts +31 -0
  100. package/dist/interactions.d.ts.map +1 -0
  101. package/dist/interactions.js +2 -0
  102. package/dist/interactions.js.map +1 -0
  103. package/dist/messages/account-sender.d.ts +9 -0
  104. package/dist/messages/account-sender.d.ts.map +1 -0
  105. package/dist/messages/account-sender.js +46 -0
  106. package/dist/messages/account-sender.js.map +1 -0
  107. package/dist/messages/contacts.d.ts +103 -0
  108. package/dist/messages/contacts.d.ts.map +1 -0
  109. package/dist/messages/contacts.js +525 -0
  110. package/dist/messages/contacts.js.map +1 -0
  111. package/dist/messages/outbox.d.ts +66 -0
  112. package/dist/messages/outbox.d.ts.map +1 -0
  113. package/dist/messages/outbox.js +167 -0
  114. package/dist/messages/outbox.js.map +1 -0
  115. package/dist/messages/receiver.d.ts +35 -0
  116. package/dist/messages/receiver.d.ts.map +1 -0
  117. package/dist/messages/receiver.js +113 -0
  118. package/dist/messages/receiver.js.map +1 -0
  119. package/dist/messages/repository.d.ts +89 -0
  120. package/dist/messages/repository.d.ts.map +1 -0
  121. package/dist/messages/repository.js +295 -0
  122. package/dist/messages/repository.js.map +1 -0
  123. package/dist/models/authentication.d.ts +37 -0
  124. package/dist/models/authentication.d.ts.map +1 -0
  125. package/dist/models/authentication.js +53 -0
  126. package/dist/models/authentication.js.map +1 -0
  127. package/dist/models/channels.d.ts +141 -0
  128. package/dist/models/channels.d.ts.map +1 -0
  129. package/dist/models/channels.js +258 -0
  130. package/dist/models/channels.js.map +1 -0
  131. package/dist/models/contacts.d.ts +68 -0
  132. package/dist/models/contacts.d.ts.map +1 -0
  133. package/dist/models/contacts.js +186 -0
  134. package/dist/models/contacts.js.map +1 -0
  135. package/dist/models/content.d.ts +37 -0
  136. package/dist/models/content.d.ts.map +1 -0
  137. package/dist/models/content.js +137 -0
  138. package/dist/models/content.js.map +1 -0
  139. package/dist/models/device-state.d.ts +8 -0
  140. package/dist/models/device-state.d.ts.map +1 -0
  141. package/dist/models/device-state.js +22 -0
  142. package/dist/models/device-state.js.map +1 -0
  143. package/dist/models/group-admission.d.ts +111 -0
  144. package/dist/models/group-admission.d.ts.map +1 -0
  145. package/dist/models/group-admission.js +153 -0
  146. package/dist/models/group-admission.js.map +1 -0
  147. package/dist/models/group-keys.d.ts +30 -0
  148. package/dist/models/group-keys.d.ts.map +1 -0
  149. package/dist/models/group-keys.js +52 -0
  150. package/dist/models/group-keys.js.map +1 -0
  151. package/dist/models/group-management.d.ts +190 -0
  152. package/dist/models/group-management.d.ts.map +1 -0
  153. package/dist/models/group-management.js +263 -0
  154. package/dist/models/group-management.js.map +1 -0
  155. package/dist/models/groups.d.ts +81 -0
  156. package/dist/models/groups.d.ts.map +1 -0
  157. package/dist/models/groups.js +127 -0
  158. package/dist/models/groups.js.map +1 -0
  159. package/dist/models/identity.d.ts +47 -0
  160. package/dist/models/identity.d.ts.map +1 -0
  161. package/dist/models/identity.js +136 -0
  162. package/dist/models/identity.js.map +1 -0
  163. package/dist/models/messages.d.ts +104 -0
  164. package/dist/models/messages.d.ts.map +1 -0
  165. package/dist/models/messages.js +168 -0
  166. package/dist/models/messages.js.map +1 -0
  167. package/dist/models/profile.d.ts +24 -0
  168. package/dist/models/profile.d.ts.map +1 -0
  169. package/dist/models/profile.js +47 -0
  170. package/dist/models/profile.js.map +1 -0
  171. package/dist/models/relay.d.ts +39 -0
  172. package/dist/models/relay.d.ts.map +1 -0
  173. package/dist/models/relay.js +160 -0
  174. package/dist/models/relay.js.map +1 -0
  175. package/dist/protocol/codec.d.ts +36 -0
  176. package/dist/protocol/codec.d.ts.map +1 -0
  177. package/dist/protocol/codec.js +144 -0
  178. package/dist/protocol/codec.js.map +1 -0
  179. package/dist/protocol/context.d.ts +14 -0
  180. package/dist/protocol/context.d.ts.map +1 -0
  181. package/dist/protocol/context.js +43 -0
  182. package/dist/protocol/context.js.map +1 -0
  183. package/dist/protocol/encoding.d.ts +15 -0
  184. package/dist/protocol/encoding.d.ts.map +1 -0
  185. package/dist/protocol/encoding.js +133 -0
  186. package/dist/protocol/encoding.js.map +1 -0
  187. package/dist/protocol/json.d.ts +16 -0
  188. package/dist/protocol/json.d.ts.map +1 -0
  189. package/dist/protocol/json.js +172 -0
  190. package/dist/protocol/json.js.map +1 -0
  191. package/dist/protocol/validation.d.ts +4 -0
  192. package/dist/protocol/validation.d.ts.map +1 -0
  193. package/dist/protocol/validation.js +18 -0
  194. package/dist/protocol/validation.js.map +1 -0
  195. package/dist/runtime/abort.d.ts +6 -0
  196. package/dist/runtime/abort.d.ts.map +1 -0
  197. package/dist/runtime/abort.js +32 -0
  198. package/dist/runtime/abort.js.map +1 -0
  199. package/dist/runtime/async-gate.d.ts +6 -0
  200. package/dist/runtime/async-gate.d.ts.map +1 -0
  201. package/dist/runtime/async-gate.js +15 -0
  202. package/dist/runtime/async-gate.js.map +1 -0
  203. package/dist/runtime/async-pulse.d.ts +7 -0
  204. package/dist/runtime/async-pulse.d.ts.map +1 -0
  205. package/dist/runtime/async-pulse.js +23 -0
  206. package/dist/runtime/async-pulse.js.map +1 -0
  207. package/dist/runtime/clock.d.ts +16 -0
  208. package/dist/runtime/clock.d.ts.map +1 -0
  209. package/dist/runtime/clock.js +62 -0
  210. package/dist/runtime/clock.js.map +1 -0
  211. package/dist/runtime/events.d.ts +11 -0
  212. package/dist/runtime/events.d.ts.map +1 -0
  213. package/dist/runtime/events.js +45 -0
  214. package/dist/runtime/events.js.map +1 -0
  215. package/dist/runtime/url.d.ts +3 -0
  216. package/dist/runtime/url.d.ts.map +1 -0
  217. package/dist/runtime/url.js +23 -0
  218. package/dist/runtime/url.js.map +1 -0
  219. package/dist/storage/signed-request.d.ts +14 -0
  220. package/dist/storage/signed-request.d.ts.map +1 -0
  221. package/dist/storage/signed-request.js +26 -0
  222. package/dist/storage/signed-request.js.map +1 -0
  223. package/dist/storage/store.d.ts +58 -0
  224. package/dist/storage/store.d.ts.map +1 -0
  225. package/dist/storage/store.js +52 -0
  226. package/dist/storage/store.js.map +1 -0
  227. package/dist/storage/transaction.d.ts +7 -0
  228. package/dist/storage/transaction.d.ts.map +1 -0
  229. package/dist/storage/transaction.js +22 -0
  230. package/dist/storage/transaction.js.map +1 -0
  231. package/dist/transport/client.d.ts +61 -0
  232. package/dist/transport/client.d.ts.map +1 -0
  233. package/dist/transport/client.js +392 -0
  234. package/dist/transport/client.js.map +1 -0
  235. package/dist/transport/discovery.d.ts +19 -0
  236. package/dist/transport/discovery.d.ts.map +1 -0
  237. package/dist/transport/discovery.js +75 -0
  238. package/dist/transport/discovery.js.map +1 -0
  239. package/dist/transport/endpoint.d.ts +6 -0
  240. package/dist/transport/endpoint.d.ts.map +1 -0
  241. package/dist/transport/endpoint.js +35 -0
  242. package/dist/transport/endpoint.js.map +1 -0
  243. package/dist/transport/http.d.ts +52 -0
  244. package/dist/transport/http.d.ts.map +1 -0
  245. package/dist/transport/http.js +128 -0
  246. package/dist/transport/http.js.map +1 -0
  247. package/dist/transport/pool.d.ts +31 -0
  248. package/dist/transport/pool.d.ts.map +1 -0
  249. package/dist/transport/pool.js +137 -0
  250. package/dist/transport/pool.js.map +1 -0
  251. package/dist/transport/relay-error.d.ts +23 -0
  252. package/dist/transport/relay-error.d.ts.map +1 -0
  253. package/dist/transport/relay-error.js +47 -0
  254. package/dist/transport/relay-error.js.map +1 -0
  255. package/dist/transport/rpc.d.ts +31 -0
  256. package/dist/transport/rpc.d.ts.map +1 -0
  257. package/dist/transport/rpc.js +56 -0
  258. package/dist/transport/rpc.js.map +1 -0
  259. package/dist/transport/session.d.ts +49 -0
  260. package/dist/transport/session.d.ts.map +1 -0
  261. package/dist/transport/session.js +169 -0
  262. package/dist/transport/session.js.map +1 -0
  263. package/dist/transport/socket.d.ts +55 -0
  264. package/dist/transport/socket.d.ts.map +1 -0
  265. package/dist/transport/socket.js +266 -0
  266. package/dist/transport/socket.js.map +1 -0
  267. package/dist/transport/subscription.d.ts +36 -0
  268. package/dist/transport/subscription.d.ts.map +1 -0
  269. package/dist/transport/subscription.js +169 -0
  270. package/dist/transport/subscription.js.map +1 -0
  271. package/package.json +35 -4
  272. package/src/channels/repository.ts +244 -0
  273. package/src/client/account-operations.ts +183 -0
  274. package/src/client/conversations.ts +95 -0
  275. package/src/client.ts +108 -0
  276. package/src/components/account.ts +206 -0
  277. package/src/components/channel.ts +253 -0
  278. package/src/components/component.ts +151 -0
  279. package/src/components/device.ts +455 -0
  280. package/src/components/group.ts +546 -0
  281. package/src/components/message.ts +253 -0
  282. package/src/components/profile.ts +179 -0
  283. package/src/crypto/groups.ts +107 -0
  284. package/src/crypto/messages.ts +129 -0
  285. package/src/crypto/primitives.ts +103 -0
  286. package/src/errors.ts +13 -0
  287. package/src/groups/account-sync.ts +144 -0
  288. package/src/groups/messages.ts +89 -0
  289. package/src/groups/operations.ts +145 -0
  290. package/src/groups/repository.ts +161 -0
  291. package/src/groups/secrets.ts +256 -0
  292. package/src/groups/state.ts +138 -0
  293. package/src/identity/identifiers.ts +41 -0
  294. package/src/identity/neo.ts +72 -0
  295. package/src/index.ts +52 -0
  296. package/src/interactions.ts +35 -0
  297. package/src/messages/account-sender.ts +33 -0
  298. package/src/messages/contacts.ts +379 -0
  299. package/src/messages/outbox.ts +152 -0
  300. package/src/messages/receiver.ts +86 -0
  301. package/src/messages/repository.ts +230 -0
  302. package/src/models/authentication.ts +63 -0
  303. package/src/models/channels.ts +155 -0
  304. package/src/models/contacts.ts +141 -0
  305. package/src/models/content.ts +105 -0
  306. package/src/models/device-state.ts +18 -0
  307. package/src/models/group-admission.ts +110 -0
  308. package/src/models/group-keys.ts +34 -0
  309. package/src/models/group-management.ts +182 -0
  310. package/src/models/groups.ts +100 -0
  311. package/src/models/identity.ts +164 -0
  312. package/src/models/messages.ts +139 -0
  313. package/src/models/profile.ts +46 -0
  314. package/src/models/relay.ts +151 -0
  315. package/src/protocol/codec.ts +144 -0
  316. package/src/protocol/context.ts +39 -0
  317. package/src/protocol/encoding.ts +106 -0
  318. package/src/protocol/json.ts +140 -0
  319. package/src/protocol/validation.ts +13 -0
  320. package/src/runtime/abort.ts +27 -0
  321. package/src/runtime/async-gate.ts +16 -0
  322. package/src/runtime/async-pulse.ts +20 -0
  323. package/src/runtime/clock.ts +63 -0
  324. package/src/runtime/events.ts +31 -0
  325. package/src/runtime/url.ts +17 -0
  326. package/src/storage/signed-request.ts +26 -0
  327. package/src/storage/store.ts +90 -0
  328. package/src/storage/transaction.ts +17 -0
  329. package/src/transport/client.ts +328 -0
  330. package/src/transport/discovery.ts +64 -0
  331. package/src/transport/endpoint.ts +32 -0
  332. package/src/transport/http.ts +129 -0
  333. package/src/transport/pool.ts +115 -0
  334. package/src/transport/relay-error.ts +46 -0
  335. package/src/transport/rpc.ts +56 -0
  336. package/src/transport/session.ts +154 -0
  337. package/src/transport/socket.ts +248 -0
  338. package/src/transport/subscription.ts +117 -0
@@ -0,0 +1,392 @@
1
+ import { createAbortController } from '../runtime/abort.js';
2
+ import { systemRandom } from '../crypto/primitives.js';
3
+ import { ProtocolError } from '../errors.js';
4
+ import { abortScope, awaitWithSignal, systemClock, throwIfAborted } from '../runtime/clock.js';
5
+ import { EventHub } from '../runtime/events.js';
6
+ import { RelayDiscovery } from './discovery.js';
7
+ import { HttpRelayTransport, RelayBackoff } from './http.js';
8
+ import { RelayError } from './relay-error.js';
9
+ import { HttpRelaySessions, RelayAuthenticator } from './session.js';
10
+ import { RpcConnection } from './socket.js';
11
+ import { RelaySubscription } from './subscription.js';
12
+ function readiness() {
13
+ let settled = false;
14
+ let resolve, reject;
15
+ const promise = new Promise((yes, no) => { resolve = yes; reject = no; });
16
+ // A notification-only client may have no readiness waiter; retain errors for later callers.
17
+ promise.then(() => undefined, () => undefined);
18
+ return { promise, get settled() { return settled; }, resolve(slot) { settled = true; resolve(slot); }, reject(error) { settled = true; reject(error); } };
19
+ }
20
+ function retryable(error) {
21
+ if (error instanceof RelayError)
22
+ return ['unauthorized', 'temporarily_unavailable', 'bad_gateway', 'rate_limited'].includes(error.code);
23
+ if (error instanceof ProtocolError)
24
+ return ['socket_closed', 'socket_error', 'notification_overflow'].includes(error.code);
25
+ if (error instanceof Error && error.name === 'TimeoutError')
26
+ return true;
27
+ // Fetch uses TypeError for connection failure; Node HTTPS preserves its system error code.
28
+ return error instanceof TypeError || error instanceof Error && 'code' in error
29
+ && ['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'EAI_AGAIN', 'ETIMEDOUT', 'EPIPE'].includes(String(error.code));
30
+ }
31
+ /** Pool-owned transport for one relay and one immutable session identity. No constructor I/O. */
32
+ export class RelayClient {
33
+ relayId;
34
+ #events = new EventHub();
35
+ #lifetime = createAbortController();
36
+ #clock;
37
+ #random;
38
+ #options;
39
+ #http;
40
+ #discovery;
41
+ #sessions;
42
+ #authenticator;
43
+ #backoff;
44
+ #httpSession;
45
+ #socket;
46
+ #opening;
47
+ #notifications;
48
+ #ready = readiness();
49
+ #generation = 0;
50
+ #connection = 'disconnected';
51
+ #authenticating = false;
52
+ #authenticationRejected = false;
53
+ #lastError;
54
+ #terminal;
55
+ #disposal;
56
+ #subscriptions = new Map();
57
+ constructor(relayId, registry, options = {}, authenticator) {
58
+ this.relayId = relayId;
59
+ this.#options = { ...options };
60
+ this.#clock = options.clock ?? systemClock;
61
+ this.#random = options.random ?? systemRandom;
62
+ this.#backoff = new RelayBackoff(this.#clock);
63
+ this.#http = new HttpRelayTransport({ ...options, backoff: this.#backoff });
64
+ this.#discovery = new RelayDiscovery(relayId, registry, this.#http, this.#clock);
65
+ if (authenticator && (authenticator.relayId !== relayId || authenticator.context.toString() !== registry.context.toString()))
66
+ throw new ProtocolError('invalid_identity', 'Authenticator does not match this relay and network.');
67
+ this.#authenticator = authenticator;
68
+ if (authenticator)
69
+ this.#sessions = new HttpRelaySessions(authenticator, this.#http);
70
+ }
71
+ get sessionMode() { return this.#authenticator?.mode; }
72
+ get isDisposed() { return this.#lifetime.signal.aborted; }
73
+ #hasValidSession() { return (this.#httpSession?.remainingSeconds ?? 0) > 0 || this.#socket !== undefined && !this.#socket.connection.failure && this.#socket.session.remainingSeconds > 0; }
74
+ get state() {
75
+ const valid = this.#hasValidSession();
76
+ return Object.freeze({ connection: this.#connection,
77
+ authentication: this.isDisposed ? 'none' : this.#authenticationRejected ? 'rejected' : valid ? this.sessionMode : this.#authenticating ? 'authenticating' : this.#httpSession || this.#socket ? 'expired' : 'none',
78
+ sessionMode: this.sessionMode, lastError: this.#lastError });
79
+ }
80
+ on(event, listener) { return this.#events.on(event, listener); }
81
+ #check(signal) { throwIfAborted(signal); throwIfAborted(this.#lifetime.signal); if (this.#terminal !== undefined)
82
+ throw this.#terminal; }
83
+ #notify(event, value) {
84
+ this.#events.notify(event, value, error => this.#publishError(this.#lastError === undefined ? error
85
+ : new AggregateError([this.#lastError, error], 'Relay operation and observer failed.')));
86
+ }
87
+ #stateChanged() { this.#notify('stateChanged', this.state); }
88
+ #publishError(error) {
89
+ this.#lastError = error;
90
+ // Do not publish another state event for observer failures: a failing state
91
+ // subscriber must not recursively trigger itself through error reporting.
92
+ this.#events.notify('errorOccurred', error, observerError => {
93
+ this.#lastError = new AggregateError([error, observerError], 'Relay operation and error observer failed.');
94
+ });
95
+ }
96
+ #report(error) {
97
+ if (error instanceof RelayError && ['unauthorized', 'device_unknown', 'invalid_signature'].includes(error.code))
98
+ this.#authenticationRejected = true;
99
+ this.#publishError(error);
100
+ this.#stateChanged();
101
+ }
102
+ #acceptHttpSession(session) {
103
+ // A public response or a cached token is not evidence that a rejected
104
+ // identity has authenticated again. Only a newly issued session clears it.
105
+ if (session !== this.#httpSession)
106
+ this.#authenticationRejected = false;
107
+ this.#httpSession = session;
108
+ }
109
+ getDescriptor(signal) { this.#check(signal); return this.#discovery.getDescriptor(signal); }
110
+ getInfo(signal) { this.#check(signal); return this.#discovery.getInfo(signal); }
111
+ async authenticate(signal) {
112
+ this.#check(signal);
113
+ if (!this.#sessions)
114
+ throw new ProtocolError('authentication_required', 'This relay client has no authentication identity.');
115
+ if (!this.#hasValidSession())
116
+ this.#authenticationRejected = false;
117
+ this.#authenticating = true;
118
+ this.#connection = 'connecting';
119
+ try {
120
+ this.#stateChanged();
121
+ const descriptor = await this.getDescriptor(signal);
122
+ this.#acceptHttpSession(await this.#sessions.get(descriptor.endpoints.find(value => value.startsWith('https://')), signal));
123
+ this.#check(signal);
124
+ this.#connection = 'connected';
125
+ this.#lastError = undefined;
126
+ }
127
+ catch (error) {
128
+ if (!signal?.aborted && !this.isDisposed)
129
+ this.#report(error);
130
+ throw error;
131
+ }
132
+ finally {
133
+ this.#authenticating = false;
134
+ this.#stateChanged();
135
+ }
136
+ }
137
+ async requestHttp(method, name, parameters, options = {}) {
138
+ this.#check(options.signal);
139
+ const scope = abortScope([options.signal, this.#lifetime.signal]);
140
+ let session;
141
+ try {
142
+ const descriptor = await this.getDescriptor(scope.signal);
143
+ const endpoint = descriptor.endpoints.find(value => value.startsWith('https://'));
144
+ if (options.authenticated !== false) {
145
+ if (!this.#sessions)
146
+ throw new ProtocolError('authentication_required', 'Establish a relay session before an authenticated request.');
147
+ session = await this.#sessions.get(endpoint, scope.signal);
148
+ this.#acceptHttpSession(session);
149
+ }
150
+ const result = await this.#http.request(endpoint, method, name, parameters, session?.getToken(endpoint), scope.signal);
151
+ this.#connection = 'connected';
152
+ this.#lastError = undefined;
153
+ this.#stateChanged();
154
+ return result;
155
+ }
156
+ catch (error) {
157
+ if (error instanceof RelayError && error.code === 'unauthorized' && session) {
158
+ this.#sessions.invalidate(session);
159
+ if (this.#httpSession === session)
160
+ this.#httpSession = undefined;
161
+ }
162
+ if (!scope.signal.aborted)
163
+ this.#report(error);
164
+ throw error;
165
+ }
166
+ finally {
167
+ scope.dispose();
168
+ }
169
+ }
170
+ async #getSocket(signal) {
171
+ this.#check(signal);
172
+ if (!this.#authenticator)
173
+ throw new ProtocolError('authentication_required', 'WebSocket connections require an authentication identity.');
174
+ if (!this.#opening) {
175
+ const opening = this.#openSocket();
176
+ this.#opening = opening;
177
+ opening.then(() => { if (this.#opening === opening)
178
+ this.#opening = undefined; }, () => { if (this.#opening === opening)
179
+ this.#opening = undefined; });
180
+ }
181
+ return awaitWithSignal(this.#opening, signal);
182
+ }
183
+ async #openSocket() {
184
+ const descriptor = await this.getDescriptor(this.#lifetime.signal);
185
+ const endpoint = descriptor.endpoints.find(value => value.startsWith('wss://'));
186
+ if (!endpoint)
187
+ throw new ProtocolError('socket_unavailable', 'The relay does not advertise WebSocket support.');
188
+ const existing = this.#socket;
189
+ if (existing && existing.connection.endpoint === endpoint && !existing.connection.failure && existing.session.remainingSeconds > 0)
190
+ return existing;
191
+ if (existing) {
192
+ existing.controller.abort();
193
+ existing.connection.dispose();
194
+ await existing.renewal;
195
+ this.#socket = undefined;
196
+ }
197
+ const connection = new RpcConnection(endpoint, { ...this.#options, clock: this.#clock, random: this.#random, backoff: this.#backoff });
198
+ const timeout = abortScope([this.#lifetime.signal], this.#options.requestTimeoutMilliseconds ?? 60000);
199
+ this.#connection = 'connecting';
200
+ this.#stateChanged();
201
+ try {
202
+ const session = await this.#authenticator.authenticate(endpoint, (name, params, signal) => connection.request(name, params, signal), timeout.signal);
203
+ this.#check(timeout.signal);
204
+ const slot = { connection, session, controller: createAbortController(), renewal: Promise.resolve(), generation: ++this.#generation };
205
+ this.#socket = slot;
206
+ this.#authenticationRejected = false;
207
+ slot.renewal = this.#renew(slot);
208
+ this.#connection = 'connected';
209
+ this.#lastError = undefined;
210
+ this.#stateChanged();
211
+ return slot;
212
+ }
213
+ catch (error) {
214
+ connection.dispose();
215
+ if (this.#socket?.connection === connection) {
216
+ const failed = this.#socket;
217
+ this.#socket = undefined;
218
+ failed.controller.abort(error);
219
+ await failed.renewal;
220
+ }
221
+ throw error;
222
+ }
223
+ finally {
224
+ timeout.dispose();
225
+ }
226
+ }
227
+ async #renew(slot) {
228
+ const scope = abortScope([this.#lifetime.signal, slot.controller.signal]);
229
+ try {
230
+ while (!scope.signal.aborted) {
231
+ const previous = slot.session;
232
+ const remaining = previous.remainingSeconds;
233
+ if (remaining <= 0)
234
+ throw new ProtocolError('expired_session', 'The WebSocket session expired.');
235
+ const due = this.#clock.monotonicMilliseconds() + Math.max(remaining * 0.8, remaining - 30) * 1000;
236
+ while (due > this.#clock.monotonicMilliseconds())
237
+ await this.#clock.delay(Math.min(60000, due - this.#clock.monotonicMilliseconds()), scope.signal);
238
+ const deadline = abortScope([scope.signal], Math.max(1, Math.min(60000, Math.floor(previous.remainingSeconds * 1000))));
239
+ try {
240
+ const renewed = await this.#authenticator.authenticate(slot.connection.endpoint, (name, params, signal) => slot.connection.request(name, params, signal), deadline.signal);
241
+ if (previous.remainingSeconds <= 0)
242
+ throw new ProtocolError('expired_session', 'Previous socket session expired before renewal completed.');
243
+ slot.session = renewed;
244
+ this.#authenticationRejected = false;
245
+ this.#stateChanged();
246
+ }
247
+ catch (error) {
248
+ if (error instanceof RelayError && error.code !== 'unauthorized' && previous.remainingSeconds > 0) {
249
+ this.#report(error);
250
+ // A rejected renewal other than unauthorized leaves the
251
+ // already accepted socket session usable until expiry.
252
+ this.#authenticationRejected = false;
253
+ this.#stateChanged();
254
+ await this.#clock.delay(Math.min(5000, previous.remainingSeconds * 1000), scope.signal);
255
+ }
256
+ else
257
+ throw error;
258
+ }
259
+ finally {
260
+ deadline.dispose();
261
+ }
262
+ }
263
+ }
264
+ catch (error) {
265
+ if (!scope.signal.aborted) {
266
+ this.#report(error);
267
+ slot.connection.fail(error);
268
+ }
269
+ }
270
+ finally {
271
+ scope.dispose();
272
+ }
273
+ }
274
+ /** Device notification reconnection restores transport only; callers synchronize after socketConnected. */
275
+ startNotifications() {
276
+ this.#check();
277
+ if (this.sessionMode !== 'device')
278
+ throw new ProtocolError('device_session_required', 'Notifications require a device session.');
279
+ this.#notifications ??= this.#dispatchNotifications();
280
+ }
281
+ async #dispatchNotifications() {
282
+ let failures = 0;
283
+ try {
284
+ while (!this.isDisposed) {
285
+ try {
286
+ const slot = await this.#getSocket(this.#lifetime.signal);
287
+ this.#ready.resolve(slot);
288
+ this.#notify('socketConnected', { generation: slot.generation });
289
+ failures = 0;
290
+ for (;;) {
291
+ const notification = await slot.connection.nextNotification(this.#lifetime.signal);
292
+ if (slot.session.remainingSeconds <= 0)
293
+ throw new ProtocolError('expired_session', 'A notification arrived after socket session expiry.');
294
+ this.#notify('notificationReceived', notification);
295
+ }
296
+ }
297
+ catch (error) {
298
+ if (this.isDisposed)
299
+ break;
300
+ this.#connection = 'disconnected';
301
+ if (this.#ready.settled)
302
+ this.#ready = readiness();
303
+ this.#report(error);
304
+ if (!retryable(error)) {
305
+ this.#terminal = error;
306
+ this.#ready.reject(error);
307
+ this.#socket?.controller.abort(error);
308
+ this.#socket?.connection.fail(error);
309
+ this.#notify('faulted', error);
310
+ return;
311
+ }
312
+ const jitter = this.#random.bytes(2);
313
+ const fraction = ((jitter[0] << 8) | jitter[1]) / 65536;
314
+ await this.#clock.delay((Math.min(30, 2 ** Math.min(failures++, 5)) + fraction) * 1000, this.#lifetime.signal);
315
+ }
316
+ }
317
+ }
318
+ catch (error) {
319
+ if (!this.isDisposed) {
320
+ this.#terminal = error;
321
+ this.#ready.reject(error);
322
+ this.#report(error);
323
+ }
324
+ }
325
+ }
326
+ async requestWebSocket(method, parameters, signal) {
327
+ this.#check(signal);
328
+ const deadline = abortScope([signal, this.#lifetime.signal], this.#options.requestTimeoutMilliseconds ?? 60000);
329
+ try {
330
+ let slot;
331
+ if (this.sessionMode === 'device') {
332
+ this.startNotifications();
333
+ slot = await awaitWithSignal(this.#ready.promise, deadline.signal);
334
+ }
335
+ else
336
+ slot = await this.#getSocket(deadline.signal);
337
+ const result = await slot.connection.request(method, parameters, deadline.signal);
338
+ this.#connection = 'connected';
339
+ this.#lastError = undefined;
340
+ this.#stateChanged();
341
+ return result;
342
+ }
343
+ catch (error) {
344
+ if (!deadline.signal.aborted)
345
+ this.#report(error);
346
+ throw error;
347
+ }
348
+ finally {
349
+ deadline.dispose();
350
+ }
351
+ }
352
+ /** Owns the complete replacement stream for this method; dispose it after stopping its update producers. */
353
+ createSubscription(method, empty, options = {}) {
354
+ this.#check(options.signal);
355
+ if (this.sessionMode !== 'device')
356
+ throw new ProtocolError('device_session_required', 'Subscriptions require a device session.');
357
+ if (method !== 'channel.subscribe' && method !== 'group.subscribe')
358
+ throw new TypeError('Unknown subscription method.');
359
+ if (this.#subscriptions.has(method))
360
+ throw new ProtocolError('subscription_in_use', 'This client already has an owner for the subscription method.');
361
+ const subscription = new RelaySubscription(method, empty, { ...options }, {
362
+ clock: this.#clock, lifetime: this.#lifetime.signal, onConnected: listener => this.on('socketConnected', listener),
363
+ ready: async (signal) => {
364
+ this.startNotifications();
365
+ const slot = await awaitWithSignal(this.#ready.promise, signal);
366
+ return { generation: slot.generation, get failure() { return slot.connection.failure; },
367
+ request: (name, params, token) => slot.connection.request(name, params, token), retire: error => slot.connection.fail(error) };
368
+ },
369
+ closed: () => { if (this.#subscriptions.get(method) === subscription)
370
+ this.#subscriptions.delete(method); },
371
+ });
372
+ this.#subscriptions.set(method, subscription);
373
+ return subscription;
374
+ }
375
+ dispose() {
376
+ return this.#disposal ??= (async () => {
377
+ const reason = new DOMException('Relay client was disposed.', 'AbortError');
378
+ this.#lifetime.abort(reason);
379
+ this.#ready.reject(reason);
380
+ this.#sessions?.dispose();
381
+ this.#discovery.dispose();
382
+ this.#http.dispose();
383
+ this.#socket?.controller.abort(reason);
384
+ this.#socket?.connection.dispose();
385
+ await Promise.allSettled([this.#opening, this.#notifications, this.#socket?.renewal, ...[...this.#subscriptions.values()].map(value => value.dispose())]);
386
+ this.#connection = 'disconnected';
387
+ this.#stateChanged();
388
+ this.#events.clear();
389
+ })();
390
+ }
391
+ }
392
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/transport/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { RelayRegistry } from '../interactions.js';
2
+ import { type RelayDescriptor, type RelayInfo } from '../models/relay.js';
3
+ import { NetworkContext } from '../protocol/context.js';
4
+ import { type RuntimeClock } from '../runtime/clock.js';
5
+ import type { HttpRelayTransport } from './http.js';
6
+ /** Resolves one trusted relay identity; descriptors, never old URLs, authorize endpoint selection. */
7
+ export declare class RelayDiscovery {
8
+ #private;
9
+ readonly relayId: string;
10
+ readonly registry: RelayRegistry;
11
+ readonly transport: HttpRelayTransport;
12
+ readonly clock: RuntimeClock;
13
+ constructor(relayId: string, registry: RelayRegistry, transport: HttpRelayTransport, clock?: RuntimeClock);
14
+ get context(): NetworkContext;
15
+ getDescriptor(signal?: AbortSignal): Promise<RelayDescriptor>;
16
+ getInfo(signal?: AbortSignal): Promise<RelayInfo>;
17
+ dispose(): void;
18
+ }
19
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/transport/discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAoF,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5J,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEtG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,sGAAsG;AACtG,qBAAa,cAAc;;IAKX,QAAQ,CAAC,OAAO,EAAE,MAAM;IAAE,QAAQ,CAAC,QAAQ,EAAE,aAAa;IAAE,QAAQ,CAAC,SAAS,EAAE,kBAAkB;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY;IAA5I,YAAqB,OAAO,EAAE,MAAM,EAAW,QAAQ,EAAE,aAAa,EAAW,SAAS,EAAE,kBAAkB,EAAW,KAAK,GAAE,YAA0B,EAGzJ;IACD,IAAI,OAAO,IAAI,cAAc,CAA0B;IAEjD,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAWlE;IAkBK,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAQtD;IAGD,OAAO,IAAI,IAAI,CAAqH;CACvI"}
@@ -0,0 +1,75 @@
1
+ import { createAbortController } from '../runtime/abort.js';
2
+ import { ProtocolError } from '../errors.js';
3
+ import { validateRelayId } from '../identity/neo.js';
4
+ import { relayDescriptorCodec, relayInfoCodec, validateRelayDescriptor, validateRelayInfo } from '../models/relay.js';
5
+ import { NetworkContext } from '../protocol/context.js';
6
+ import { awaitWithSignal, systemClock, throwIfAborted } from '../runtime/clock.js';
7
+ import { webEndpoint } from './endpoint.js';
8
+ /** Resolves one trusted relay identity; descriptors, never old URLs, authorize endpoint selection. */
9
+ export class RelayDiscovery {
10
+ relayId;
11
+ registry;
12
+ transport;
13
+ clock;
14
+ #lifetime = createAbortController();
15
+ #context;
16
+ #cached;
17
+ #pending;
18
+ constructor(relayId, registry, transport, clock = systemClock) {
19
+ this.relayId = relayId;
20
+ this.registry = registry;
21
+ this.transport = transport;
22
+ this.clock = clock;
23
+ validateRelayId(relayId);
24
+ this.#context = NetworkContext.parse(registry.context.toString());
25
+ }
26
+ get context() { return this.#context; }
27
+ async getDescriptor(signal) {
28
+ throwIfAborted(signal);
29
+ throwIfAborted(this.#lifetime.signal);
30
+ if (this.registry.context.toString() !== this.#context.toString())
31
+ throw new ProtocolError('context_changed', 'The relay registry network context has changed.');
32
+ if (this.#cached && this.#cached.expiresAt > this.clock.nowSeconds())
33
+ return this.#copy(this.#cached);
34
+ if (!this.#pending) {
35
+ const pending = this.#discover();
36
+ this.#pending = pending;
37
+ pending.then(value => { this.#cached = value; if (this.#pending === pending)
38
+ this.#pending = undefined; }, () => { if (this.#pending === pending)
39
+ this.#pending = undefined; });
40
+ }
41
+ return this.#copy(await awaitWithSignal(this.#pending, signal));
42
+ }
43
+ async #discover() {
44
+ const signal = this.#lifetime.signal;
45
+ const entry = await this.registry.getRelay(this.relayId, signal);
46
+ throwIfAborted(signal);
47
+ if (this.registry.context.toString() !== this.#context.toString())
48
+ throw new ProtocolError('context_changed', 'The registry network context changed during discovery.');
49
+ if (!entry || entry.relayId !== this.relayId || entry.status !== 'active')
50
+ throw new ProtocolError('inactive_relay', 'The registry does not identify an active relay with the requested ID.');
51
+ webEndpoint(entry.endpoint, 'https:');
52
+ const wire = await this.transport.request(entry.endpoint, 'GET', 'relay.descriptor', undefined, undefined, signal);
53
+ if (wire === undefined)
54
+ throw new ProtocolError('missing_result', 'Relay discovery returned no descriptor.');
55
+ const descriptor = relayDescriptorCodec.decode(wire);
56
+ validateRelayDescriptor(descriptor, this.#context, this.clock.nowSeconds());
57
+ if (descriptor.relayId !== this.relayId)
58
+ throw new ProtocolError('invalid_identity', 'The descriptor does not identify the registered relay.');
59
+ throwIfAborted(signal);
60
+ return descriptor;
61
+ }
62
+ async getInfo(signal) {
63
+ const descriptor = await this.getDescriptor(signal);
64
+ const endpoint = descriptor.endpoints.find(endpoint => endpoint.startsWith('https://'));
65
+ const wire = await this.transport.request(endpoint, 'GET', 'relay.info', undefined, undefined, signal);
66
+ if (wire === undefined)
67
+ throw new ProtocolError('missing_result', 'Relay info returned no result.');
68
+ const info = relayInfoCodec.decode(wire);
69
+ validateRelayInfo(info, descriptor);
70
+ return info;
71
+ }
72
+ #copy(value) { return relayDescriptorCodec.decode(relayDescriptorCodec.encode(value)); }
73
+ dispose() { this.#cached = undefined; this.#lifetime.abort(new DOMException('Relay discovery was disposed.', 'AbortError')); }
74
+ }
75
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/transport/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,uBAAuB,EAAE,iBAAiB,EAAwC,MAAM,oBAAoB,CAAC;AAC5J,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,sGAAsG;AACtG,MAAM,OAAO,cAAc;IAKF,OAAO;IAAmB,QAAQ;IAA0B,SAAS;IAA+B,KAAK;IAJrH,SAAS,GAAG,qBAAqB,EAAE,CAAC;IACpC,QAAQ,CAAiB;IAClC,OAAO,CAA8B;IACrC,QAAQ,CAAuC;IAC/C,YAAqB,OAAe,EAAW,QAAuB,EAAW,SAA6B,EAAW,KAAK,GAAiB,WAAW;uBAArI,OAAO;wBAAmB,QAAQ;yBAA0B,SAAS;qBAA+B,KAAK;QAC1H,eAAe,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,OAAO,KAAqB,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvD,KAAK,CAAC,aAAa,CAAC,MAAoB;QACpC,cAAc,CAAC,MAAM,CAAC,CAAC;QAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,EAAE,iDAAiD,CAAC,CAAC;QACjK,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;gBAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,EACrG,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;gBAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,SAAS;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACjE,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,EAAE,wDAAwD,CAAC,CAAC;QACxK,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;YAAE,MAAM,IAAI,aAAa,CAAC,gBAAgB,EAAE,uEAAuE,CAAC,CAAC;QAC9L,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QACnH,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,aAAa,CAAC,gBAAgB,EAAE,yCAAyC,CAAC,CAAC;QAC7G,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,uBAAuB,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5E,IAAI,UAAU,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,wDAAwD,CAAC,CAAC;QAC/I,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAoB;QAC9B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAE,CAAC;QACzF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QACvG,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,aAAa,CAAC,gBAAgB,EAAE,gCAAgC,CAAC,CAAC;QACpG,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,KAAsB,IAAqB,OAAO,oBAAoB,CAAC,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1H,OAAO,KAAW,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,+BAA+B,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CACvI"}
@@ -0,0 +1,6 @@
1
+ /** Validates before URL parsing so a parser cannot silently repair unsafe input. */
2
+ export declare function webEndpoint(endpoint: string, protocol?: 'https:' | 'wss:'): URL;
3
+ /** Authentication maps WSS to HTTPS and excludes the endpoint path. */
4
+ export declare function relayOrigin(endpoint: string): string;
5
+ export declare function validateMethodName(name: string): void;
6
+ //# sourceMappingURL=endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/transport/endpoint.ts"],"names":[],"mappings":"AAIA,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,GAAG,CAe/E;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGrD"}
@@ -0,0 +1,35 @@
1
+ import { ProtocolError } from '../errors.js';
2
+ import { encodeUtf8 } from '../protocol/encoding.js';
3
+ import { parseAbsoluteUrl } from '../runtime/url.js';
4
+ /** Validates before URL parsing so a parser cannot silently repair unsafe input. */
5
+ export function webEndpoint(endpoint, protocol) {
6
+ if (typeof endpoint !== 'string' || !/^(https|wss):\/\//.test(endpoint) || encodeUtf8(endpoint).length > 512
7
+ || /[\s\p{Cc}?#\\]/u.test(endpoint))
8
+ throw new ProtocolError('invalid_endpoint', 'Expected an HTTPS or WSS relay endpoint without whitespace, query, fragment or backslash.');
9
+ const authority = endpoint.slice(endpoint.indexOf('://') + 3).split('/')[0];
10
+ if (authority.length === 0 || authority.includes('@') || authority.includes('%'))
11
+ throw new ProtocolError('invalid_endpoint', 'Relay endpoints must have a host and cannot contain user information or an escaped authority.');
12
+ // URL accepts malformed percent escapes in paths; the protocol does not.
13
+ if (/%(?![0-9a-fA-F]{2})/.test(endpoint))
14
+ throw new ProtocolError('invalid_endpoint', 'Malformed endpoint escape.');
15
+ let url;
16
+ try {
17
+ url = parseAbsoluteUrl(endpoint);
18
+ }
19
+ catch (cause) {
20
+ throw new ProtocolError('invalid_endpoint', 'Invalid relay endpoint.', { cause });
21
+ }
22
+ if (!url.hostname || (protocol !== undefined && url.protocol !== protocol))
23
+ throw new ProtocolError('invalid_endpoint', 'Unexpected relay endpoint protocol or host.');
24
+ return url;
25
+ }
26
+ /** Authentication maps WSS to HTTPS and excludes the endpoint path. */
27
+ export function relayOrigin(endpoint) {
28
+ const url = webEndpoint(endpoint);
29
+ return `https://${url.hostname.toLowerCase()}${url.port === '' || url.port === '443' ? '' : `:${url.port}`}`;
30
+ }
31
+ export function validateMethodName(name) {
32
+ if (!/^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/.test(name) || /\s/.test(name))
33
+ throw new ProtocolError('invalid_method', 'Invalid relay method name.');
34
+ }
35
+ //# sourceMappingURL=endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/transport/endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,oFAAoF;AACpF,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,QAA4B;IACtE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,GAAG;WACrG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;QACnC,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,2FAA2F,CAAC,CAAC;IAC7I,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IAC7E,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC5E,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,+FAA+F,CAAC,CAAC;IACjJ,yEAAyE;IACzE,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;IACpH,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QAAC,GAAG,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAAC,CAAC;IACzC,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,yBAAyB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAAC,CAAC;IACpG,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACtE,MAAM,IAAI,aAAa,CAAC,kBAAkB,EAAE,6CAA6C,CAAC,CAAC;IAC/F,OAAO,GAAG,CAAC;AACf,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,WAAW,CAAC,QAAgB;IACxC,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,WAAW,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;AACjH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC3C,IAAI,CAAC,yCAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACxE,MAAM,IAAI,aAAa,CAAC,gBAAgB,EAAE,4BAA4B,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { type JsonObject, type JsonValue } from '../protocol/json.js';
2
+ import { type RuntimeClock } from '../runtime/clock.js';
3
+ import { type RelayFailure } from './relay-error.js';
4
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
5
+ export interface RelayFetchInit {
6
+ readonly method: HttpMethod;
7
+ readonly headers: Readonly<Record<string, string>>;
8
+ readonly body?: string;
9
+ readonly signal: AbortSignal;
10
+ readonly redirect: 'error';
11
+ readonly credentials: 'omit';
12
+ readonly cache: 'no-store';
13
+ readonly referrerPolicy: 'no-referrer';
14
+ }
15
+ export interface RelayFetchResponse {
16
+ readonly status: number;
17
+ readonly redirected?: boolean;
18
+ readonly type?: string;
19
+ readonly headers: {
20
+ get(name: string): string | null;
21
+ };
22
+ readonly body?: {
23
+ cancel(): Promise<void>;
24
+ } | null;
25
+ arrayBuffer(): Promise<ArrayBuffer>;
26
+ }
27
+ /** An injected fetch must honor redirect:error and credentials:omit and must never replay a business request. */
28
+ export type RelayFetch = (url: string, init: RelayFetchInit) => Promise<RelayFetchResponse>;
29
+ /** Share between HTTP and WebSocket for one relay. A rejected request is never automatically retried. */
30
+ export declare class RelayBackoff {
31
+ #private;
32
+ readonly clock: RuntimeClock;
33
+ constructor(clock?: RuntimeClock);
34
+ apply(failure: RelayFailure): void;
35
+ wait(signal?: AbortSignal): Promise<void>;
36
+ }
37
+ /** Strict media-type parsing avoids accepting a second hidden non-UTF8 charset. */
38
+ export declare function validateJsonContentType(value: string | null): void;
39
+ export interface HttpRelayTransportOptions {
40
+ readonly fetch?: RelayFetch;
41
+ readonly backoff?: RelayBackoff;
42
+ readonly requestTimeoutMilliseconds?: number;
43
+ }
44
+ export declare class HttpRelayTransport {
45
+ #private;
46
+ readonly backoff: RelayBackoff;
47
+ constructor(options?: HttpRelayTransportOptions);
48
+ request(endpoint: string, method: HttpMethod, name: string, parameters?: JsonObject, token?: string, signal?: AbortSignal): Promise<JsonValue | undefined>;
49
+ /** Cancels active requests and makes later requests fail. */
50
+ dispose(): void;
51
+ }
52
+ //# sourceMappingURL=http.d.ts.map