@calimero-network/mero-js 24.0.0 → 24.1.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.
@@ -155,6 +155,54 @@ export interface CloudRelay {
155
155
  canExecute: boolean;
156
156
  lastSeenAt?: string | null;
157
157
  confirmedAt?: string | null;
158
+ /**
159
+ * How far along this relay's admission is, as the cloud judges it:
160
+ * `'confirmed'` (in), `'pending'` (trying), `'refused'` (alive and turned
161
+ * away), `'absent'` (stopped talking before getting in). `null` from a cloud
162
+ * that predates the field. A string, not a closed union, so a verdict the
163
+ * cloud adds later is passed through rather than dropped.
164
+ */
165
+ admission: string | null;
166
+ /** The cloud's one-line explanation of `admission`, for a person; `null` when none. */
167
+ admissionHint: string | null;
168
+ /**
169
+ * What the relay itself reported about its latest attempt to join, reasons
170
+ * included — or `null` when it has reported nothing (an older fleet node or
171
+ * cloud, or a relay assigned since its last report).
172
+ */
173
+ join: CloudRelayJoin | null;
174
+ }
175
+ /**
176
+ * A fleet node's own account of its latest attempt to join a namespace.
177
+ *
178
+ * A refusal happens peer to peer, between the node and the namespace's
179
+ * admitters, so this is the only place a client learns WHY a relay is stuck:
180
+ * the node forwards what each admitter it asked directly answered.
181
+ */
182
+ export interface CloudRelayJoin {
183
+ /**
184
+ * `'admitted'` (in, or an admitter said yes and the key is on its way),
185
+ * `'refused'` (every admitter asked declined; see `refusals`), `'waiting'`
186
+ * (nobody answered directly yet), or `'error'` (the attempt itself failed;
187
+ * see `error`). Passed through as sent.
188
+ */
189
+ state: string;
190
+ /** Consecutive attempts without admission, as the node counts them. */
191
+ attempts: number;
192
+ /**
193
+ * Each directly-asked admitter that declined: its libp2p peer id and its
194
+ * reason, verbatim. Text to show a person, never to parse — the most useful
195
+ * one is "was removed from group … and cannot rejoin; an admin must re-add
196
+ * them", which the namespace owner can fix by re-adding the node.
197
+ */
198
+ refusals: Array<{
199
+ peer: string;
200
+ reason: string;
201
+ }>;
202
+ /** Why the attempt itself failed, when `state` is `'error'`. */
203
+ error: string | null;
204
+ /** When the node reported this, ISO 8601 (UTC, no offset), or `null`. */
205
+ reportedAt: string | null;
158
206
  }
159
207
  /**
160
208
  * One node serving a namespace, as a caller with no cloud account sees it.
@@ -66,6 +66,27 @@ function teeRoleOf(row) {
66
66
  export function pickExecutingRelay(relays) {
67
67
  return (relays.find((r) => r.canExecute && r.relayUrl !== null && r.executorAccount !== null) ?? null);
68
68
  }
69
+ /** `join` from a relay row, or `null` when absent or not an object. */
70
+ function joinOf(row) {
71
+ const raw = row.join;
72
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
73
+ return null;
74
+ const join = raw;
75
+ if (typeof join.state !== 'string')
76
+ return null;
77
+ const refusals = Array.isArray(join.refusals)
78
+ ? join.refusals
79
+ .filter((r) => !!r && typeof r === 'object')
80
+ .map((r) => ({ peer: String(r.peer ?? ''), reason: String(r.reason ?? '') }))
81
+ : [];
82
+ return {
83
+ state: join.state,
84
+ attempts: typeof join.attempts === 'number' ? join.attempts : 0,
85
+ refusals,
86
+ error: typeof join.error === 'string' ? join.error : null,
87
+ reportedAt: typeof join.reported_at === 'string' ? join.reported_at : null,
88
+ };
89
+ }
69
90
  const ACCOUNT_HEX = /^[0-9a-f]{64}$/;
70
91
  function accountHexOrNull(value) {
71
92
  return typeof value === 'string' && ACCOUNT_HEX.test(value) ? value : null;
@@ -349,6 +370,9 @@ export class CloudClient {
349
370
  canExecute: canExecuteOf(row, authorshipReady && relayUrl !== null && executorAccount !== null),
350
371
  lastSeenAt: row.last_seen_at ?? null,
351
372
  confirmedAt: row.confirmed_at ?? null,
373
+ admission: typeof row.admission === 'string' ? row.admission : null,
374
+ admissionHint: typeof row.admission_hint === 'string' ? row.admission_hint : null,
375
+ join: joinOf(row),
352
376
  };
353
377
  });
354
378
  }
@@ -1,5 +1,5 @@
1
1
  export { CloudClient, admitterAddrsFromNetworkStatus, AccountHaRefusedError, AccountNotLinkedError, AccountLinkedToSeveralUsersError, HaRequestPendingError, UnknownRelayError, RelayNotDialableError, } from './cloud-client.js';
2
- export type { CloudClientConfig, CloudSession, CloudNamespace, CloudRelay, CloudAccountRelay, CloudNamespaceNode, CloudNamespaceRouting, CloudMachine, CloudMachineNamespace, CloudLinkedAccount, CloudLinkedAccounts, CloudAccountLink, AccountLinkChallenge, AccountLinkProof, AccountLinkHandoff, AccountLinkCallback, AccountLoginChallenge, AccountLoginProof, EnableHAOptions, DisableHAOptions, EnableHaAsAccountOptions, } from './cloud-client.js';
2
+ export type { CloudClientConfig, CloudSession, CloudNamespace, CloudRelay, CloudRelayJoin, CloudAccountRelay, CloudNamespaceNode, CloudNamespaceRouting, CloudMachine, CloudMachineNamespace, CloudLinkedAccount, CloudLinkedAccounts, CloudAccountLink, AccountLinkChallenge, AccountLinkProof, AccountLinkHandoff, AccountLinkCallback, AccountLoginChallenge, AccountLoginProof, EnableHAOptions, DisableHAOptions, EnableHaAsAccountOptions, } from './cloud-client.js';
3
3
  export { connectCloud, connectCloudWithAccount } from './connect.js';
4
4
  export type { ConnectCloudOptions, ConnectCloudWithAccountOptions, CloudConnection, } from './connect.js';
5
5
  export { signRoutingChallenge, routingProofHeaders } from './routing-proof.js';