@calimero-network/mero-js 26.11.0 → 27.0.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.
- package/README.md +73 -288
- package/dist/cloud-v2/attestation.d.ts +91 -0
- package/dist/cloud-v2/attestation.js +135 -0
- package/dist/cloud-v2/capabilities.d.ts +30 -0
- package/dist/cloud-v2/capabilities.js +31 -0
- package/dist/cloud-v2/client.d.ts +426 -0
- package/dist/cloud-v2/client.js +646 -0
- package/dist/cloud-v2/errors.d.ts +98 -0
- package/dist/cloud-v2/errors.js +165 -0
- package/dist/cloud-v2/index.d.ts +10 -0
- package/dist/cloud-v2/index.js +5 -0
- package/dist/cloud-v2/passkey.d.ts +27 -0
- package/dist/cloud-v2/passkey.js +73 -0
- package/dist/crypto/internal.d.ts +3 -37
- package/dist/crypto/internal.js +3 -72
- package/dist/index.browser.mjs +4 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +1750 -12772
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -56
- package/dist/index.js +14 -75
- package/dist/index.mjs +1750 -12772
- package/dist/index.mjs.map +4 -4
- package/dist/sealed/index.d.ts +4 -4
- package/dist/sealed/index.js +2 -2
- package/dist/sealed/release.d.ts +21 -76
- package/dist/sealed/release.js +24 -108
- package/dist/sealed/sealed.d.ts +8 -56
- package/dist/sealed/sealed.js +11 -89
- package/dist/sealed/verify.d.ts +7 -13
- package/dist/sealed/verify.js +3 -7
- package/package.json +8 -13
- package/dist/account/account-admin.d.ts +0 -80
- package/dist/account/account-admin.js +0 -346
- package/dist/account/account.d.ts +0 -196
- package/dist/account/account.js +0 -269
- package/dist/account/application-id.d.ts +0 -50
- package/dist/account/application-id.js +0 -83
- package/dist/account/bootstrap-from-invitation.d.ts +0 -110
- package/dist/account/bootstrap-from-invitation.js +0 -80
- package/dist/account/create-context.d.ts +0 -103
- package/dist/account/create-context.js +0 -267
- package/dist/account/govern.d.ts +0 -24
- package/dist/account/govern.js +0 -50
- package/dist/account/index.d.ts +0 -26
- package/dist/account/index.js +0 -15
- package/dist/account/join-as-account.d.ts +0 -23
- package/dist/account/join-as-account.js +0 -34
- package/dist/account/join-with-node.d.ts +0 -115
- package/dist/account/join-with-node.js +0 -161
- package/dist/account/node-admin.d.ts +0 -20
- package/dist/account/node-admin.js +0 -33
- package/dist/account/relay-from-invitation.d.ts +0 -137
- package/dist/account/relay-from-invitation.js +0 -180
- package/dist/account/relay-login-error.d.ts +0 -32
- package/dist/account/relay-login-error.js +0 -34
- package/dist/account/session.d.ts +0 -266
- package/dist/account/session.js +0 -915
- package/dist/account/wordlist.d.ts +0 -16
- package/dist/account/wordlist.js +0 -273
- package/dist/admin-api/admin-client.d.ts +0 -688
- package/dist/admin-api/admin-client.js +0 -1230
- package/dist/admin-api/admin-factory.d.ts +0 -14
- package/dist/admin-api/admin-factory.js +0 -22
- package/dist/admin-api/admin-types.d.ts +0 -2046
- package/dist/admin-api/admin-types.js +0 -12
- package/dist/admin-api/index.d.ts +0 -4
- package/dist/admin-api/index.js +0 -5
- package/dist/admin-api/redeem-invitation.d.ts +0 -101
- package/dist/admin-api/redeem-invitation.js +0 -200
- package/dist/auth/index.d.ts +0 -34
- package/dist/auth/index.js +0 -67
- package/dist/auth-api/auth-client.d.ts +0 -31
- package/dist/auth-api/auth-client.js +0 -117
- package/dist/auth-api/auth-factory.d.ts +0 -7
- package/dist/auth-api/auth-factory.js +0 -41
- package/dist/auth-api/auth-types.d.ts +0 -130
- package/dist/auth-api/auth-types.js +0 -2
- package/dist/auth-api/index.d.ts +0 -3
- package/dist/auth-api/index.js +0 -4
- package/dist/capabilities.d.ts +0 -84
- package/dist/capabilities.js +0 -117
- package/dist/cloud/account-ownership.d.ts +0 -63
- package/dist/cloud/account-ownership.js +0 -87
- package/dist/cloud/cloud-client.d.ts +0 -949
- package/dist/cloud/cloud-client.js +0 -1068
- package/dist/cloud/connect.d.ts +0 -213
- package/dist/cloud/connect.js +0 -260
- package/dist/cloud/enrol-redirect.d.ts +0 -181
- package/dist/cloud/enrol-redirect.js +0 -244
- package/dist/cloud/index.d.ts +0 -12
- package/dist/cloud/index.js +0 -10
- package/dist/cloud/link-redirect.d.ts +0 -95
- package/dist/cloud/link-redirect.js +0 -121
- package/dist/cloud/link-state.d.ts +0 -36
- package/dist/cloud/link-state.js +0 -104
- package/dist/cloud/routing-proof.d.ts +0 -113
- package/dist/cloud/routing-proof.js +0 -96
- package/dist/device-cert/device-cert.d.ts +0 -189
- package/dist/device-cert/device-cert.js +0 -239
- package/dist/device-cert/device-scope.d.ts +0 -58
- package/dist/device-cert/device-scope.js +0 -76
- package/dist/device-cert/index.d.ts +0 -4
- package/dist/device-cert/index.js +0 -3
- package/dist/ephemeral/codec.d.ts +0 -4
- package/dist/ephemeral/codec.js +0 -12
- package/dist/ephemeral/index.d.ts +0 -57
- package/dist/ephemeral/index.js +0 -101
- package/dist/ephemeral/types.d.ts +0 -27
- package/dist/ephemeral/types.js +0 -1
- package/dist/errors/classify.d.ts +0 -65
- package/dist/errors/classify.js +0 -117
- package/dist/errors/index.d.ts +0 -2
- package/dist/errors/index.js +0 -1
- package/dist/events/group.d.ts +0 -95
- package/dist/events/group.js +0 -10
- package/dist/events/index.d.ts +0 -5
- package/dist/events/index.js +0 -2
- package/dist/events/sse.d.ts +0 -127
- package/dist/events/sse.js +0 -469
- package/dist/events/ws.d.ts +0 -57
- package/dist/events/ws.js +0 -212
- package/dist/http-client/api-response.d.ts +0 -15
- package/dist/http-client/api-response.js +0 -1
- package/dist/http-client/http-factory.d.ts +0 -71
- package/dist/http-client/http-factory.js +0 -68
- package/dist/http-client/http-types.d.ts +0 -87
- package/dist/http-client/http-types.js +0 -1
- package/dist/http-client/index.d.ts +0 -7
- package/dist/http-client/index.js +0 -11
- package/dist/http-client/path-segment.d.ts +0 -1
- package/dist/http-client/path-segment.js +0 -8
- package/dist/http-client/retry.d.ts +0 -5
- package/dist/http-client/retry.js +0 -82
- package/dist/http-client/signal-utils.d.ts +0 -2
- package/dist/http-client/signal-utils.js +0 -41
- package/dist/http-client/web-client.d.ts +0 -80
- package/dist/http-client/web-client.js +0 -557
- package/dist/invitation/index.d.ts +0 -2
- package/dist/invitation/index.js +0 -2
- package/dist/invitation/invitation.d.ts +0 -106
- package/dist/invitation/invitation.js +0 -104
- package/dist/login/index.d.ts +0 -4
- package/dist/login/index.js +0 -3
- package/dist/login/login.d.ts +0 -111
- package/dist/login/login.js +0 -110
- package/dist/login/session.d.ts +0 -124
- package/dist/login/session.js +0 -141
- package/dist/mero-js.d.ts +0 -231
- package/dist/mero-js.js +0 -469
- package/dist/namespace-op/index.d.ts +0 -2
- package/dist/namespace-op/index.js +0 -3
- package/dist/namespace-op/namespace-op.d.ts +0 -150
- package/dist/namespace-op/namespace-op.js +0 -191
- package/dist/nodeDiscovery.d.ts +0 -47
- package/dist/nodeDiscovery.js +0 -101
- package/dist/owner-op/index.d.ts +0 -2
- package/dist/owner-op/index.js +0 -3
- package/dist/owner-op/owner-op.d.ts +0 -119
- package/dist/owner-op/owner-op.js +0 -214
- package/dist/presence/relay-presence.d.ts +0 -56
- package/dist/presence/relay-presence.js +0 -107
- package/dist/presence/statement.d.ts +0 -12
- package/dist/presence/statement.js +0 -17
- package/dist/relay/index.d.ts +0 -4
- package/dist/relay/index.js +0 -2
- package/dist/relay/nonce-source.d.ts +0 -72
- package/dist/relay/nonce-source.js +0 -111
- package/dist/relay/relay-client.d.ts +0 -472
- package/dist/relay/relay-client.js +0 -518
- package/dist/relay-attestation/attest-node-key.d.ts +0 -66
- package/dist/relay-attestation/attest-node-key.js +0 -110
- package/dist/relay-attestation/index.d.ts +0 -1
- package/dist/relay-attestation/index.js +0 -1
- package/dist/request/caller-proof.d.ts +0 -43
- package/dist/request/caller-proof.js +0 -36
- package/dist/request/index.d.ts +0 -3
- package/dist/request/index.js +0 -3
- package/dist/request/proof-signer.d.ts +0 -49
- package/dist/request/proof-signer.js +0 -59
- package/dist/request/request-sig.d.ts +0 -99
- package/dist/request/request-sig.js +0 -95
- package/dist/request-proof/authorizer.d.ts +0 -41
- package/dist/request-proof/authorizer.js +0 -60
- package/dist/request-proof/index.d.ts +0 -4
- package/dist/request-proof/index.js +0 -2
- package/dist/request-proof/request-proof.d.ts +0 -53
- package/dist/request-proof/request-proof.js +0 -95
- package/dist/rpc/index.d.ts +0 -64
- package/dist/rpc/index.js +0 -78
- package/dist/signer/index.d.ts +0 -2
- package/dist/signer/index.js +0 -3
- package/dist/signer/signer.d.ts +0 -92
- package/dist/signer/signer.js +0 -147
- package/dist/token-store/index.d.ts +0 -27
- package/dist/token-store/index.js +0 -62
- package/dist/transport/index.d.ts +0 -6
- package/dist/transport/index.js +0 -3
- package/dist/transport/mero-client.d.ts +0 -294
- package/dist/transport/mero-client.js +0 -386
- package/dist/transport/relay-observer.d.ts +0 -152
- package/dist/transport/relay-observer.js +0 -173
- package/dist/transport/relay-transport.d.ts +0 -73
- package/dist/transport/relay-transport.js +0 -94
- package/dist/transport/types.d.ts +0 -100
- package/dist/transport/types.js +0 -32
- package/dist/types/api-response.d.ts +0 -15
- package/dist/types/api-response.js +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/warrant/creation-warrant.d.ts +0 -163
- package/dist/warrant/creation-warrant.js +0 -194
- package/dist/warrant/governance-op.d.ts +0 -202
- package/dist/warrant/governance-op.js +0 -355
- package/dist/warrant/governance-warrant.d.ts +0 -124
- package/dist/warrant/governance-warrant.js +0 -164
- package/dist/warrant/index.d.ts +0 -8
- package/dist/warrant/index.js +0 -5
- package/dist/warrant/warrant.d.ts +0 -188
- package/dist/warrant/warrant.js +0 -202
package/dist/login/session.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Obtain a session on a node using only a device key — the handshake around
|
|
3
|
-
* {@link signLoginStatement}.
|
|
4
|
-
*
|
|
5
|
-
* Signing a statement was never the whole job. A client also has to fetch a
|
|
6
|
-
* challenge, mint a session keypair, assemble a request body whose shape it
|
|
7
|
-
* cannot see from here, and read a token out of the reply. Until now every
|
|
8
|
-
* consumer wrote those two HTTP calls by hand, which is how the same three
|
|
9
|
-
* mistakes kept being available to make:
|
|
10
|
-
*
|
|
11
|
-
* 1. **Asking for permissions.** `POST /auth/token` takes an optional
|
|
12
|
-
* `permissions` list. Left unset, the node grants the account-proof
|
|
13
|
-
* provider's own scopes — `context:intent`, `context:query`,
|
|
14
|
-
* `context:subscribe` — which are the whole delegated surface and
|
|
15
|
-
* deliberately nothing above it. This module never sends the field.
|
|
16
|
-
* `authenticate()` in this same package hardcodes `['admin']` (#84); a
|
|
17
|
-
* device-key session would be refused for that and should never ask.
|
|
18
|
-
* 2. **Learning the node's key from the node.** {@link LoginConfig.node} is
|
|
19
|
-
* required and has no default, because a value read from the challenge
|
|
20
|
-
* response would let whoever answered choose what the device signs about.
|
|
21
|
-
* That is the whole attack the field exists to stop, so the awkwardness of
|
|
22
|
-
* having to supply it is the point rather than something to smooth away.
|
|
23
|
-
* 3. **Losing the refresh token.** A browser tab outlives a short-lived
|
|
24
|
-
* session, so both tokens are returned. Nothing here refreshes on a timer
|
|
25
|
-
* (#87, #88 track that); this only makes it possible without a second
|
|
26
|
-
* breaking change.
|
|
27
|
-
*
|
|
28
|
-
* **The session key never leaves.** It is minted here, the device key signs
|
|
29
|
-
* over it once, and the secret half is handed back to the caller. That is what
|
|
30
|
-
* keeps a device key off the wire for the life of a session: a leaked token
|
|
31
|
-
* cannot be escalated into use of the key that authorised it.
|
|
32
|
-
*/
|
|
33
|
-
import { HTTPError } from '../http-client/web-client.js';
|
|
34
|
-
import { derivePublicKey, hex } from '../crypto/internal.js';
|
|
35
|
-
import { signLoginStatement } from './login.js';
|
|
36
|
-
import { resolveSigner } from '../signer/signer.js';
|
|
37
|
-
/** Seconds a statement stays valid unless told otherwise. */
|
|
38
|
-
const DEFAULT_TTL_SECONDS = 300;
|
|
39
|
-
/**
|
|
40
|
-
* Mint the ephemeral keypair a session speaks with.
|
|
41
|
-
*
|
|
42
|
-
* An ed25519 secret *is* 32 random bytes, so this needs no key generation
|
|
43
|
-
* ceremony — `getRandomValues` and the same derivation every other signer here
|
|
44
|
-
* uses. Exported because a caller that wants to persist a session across a page
|
|
45
|
-
* reload needs to mint the pair itself and keep the secret.
|
|
46
|
-
*/
|
|
47
|
-
export async function generateSessionKey() {
|
|
48
|
-
const secret = hex(crypto.getRandomValues(new Uint8Array(32)));
|
|
49
|
-
return { publicKey: hex(await derivePublicKey(secret)), secret };
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Log in with a device key and return the session.
|
|
53
|
-
*
|
|
54
|
-
* The challenge is fetched immediately before signing on purpose: it is
|
|
55
|
-
* single-use and short-lived, so a statement minted against a stale one is
|
|
56
|
-
* refused before any signature work is done.
|
|
57
|
-
*
|
|
58
|
-
* @throws {HTTPError} if the node refuses the challenge or the token request.
|
|
59
|
-
*/
|
|
60
|
-
export async function login(config) {
|
|
61
|
-
const baseUrl = config.nodeUrl.replace(/\/+$/, '');
|
|
62
|
-
const timeoutMs = config.timeoutMs ?? 10000;
|
|
63
|
-
const request = async (path, init) => {
|
|
64
|
-
const controller = new AbortController();
|
|
65
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
66
|
-
let response;
|
|
67
|
-
try {
|
|
68
|
-
// Called as `globalThis.fetch(...)`, never through a detached reference:
|
|
69
|
-
// a browser's fetch throws "Illegal invocation" when its receiver is lost.
|
|
70
|
-
const requestInit = { ...init, signal: controller.signal };
|
|
71
|
-
response = config.fetch
|
|
72
|
-
? await config.fetch(`${baseUrl}${path}`, requestInit)
|
|
73
|
-
: await globalThis.fetch(`${baseUrl}${path}`, requestInit);
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
throw new HTTPError(0, err instanceof Error ? err.name : 'NetworkError', `${baseUrl}${path}`, new Headers(), err instanceof Error ? err.message : String(err));
|
|
77
|
-
}
|
|
78
|
-
finally {
|
|
79
|
-
clearTimeout(timer);
|
|
80
|
-
}
|
|
81
|
-
const text = await response.text().catch(() => '');
|
|
82
|
-
if (!response.ok) {
|
|
83
|
-
throw new HTTPError(response.status, response.statusText, `${baseUrl}${path}`, response.headers, text);
|
|
84
|
-
}
|
|
85
|
-
return text ? JSON.parse(text) : {};
|
|
86
|
-
};
|
|
87
|
-
const challengeBody = (await request('/auth/challenge', {
|
|
88
|
-
method: 'GET',
|
|
89
|
-
headers: { Accept: 'application/json' },
|
|
90
|
-
}));
|
|
91
|
-
// The node has spelled this both bare and wrapped in `data`; accept either
|
|
92
|
-
// rather than couple a login to one envelope revision.
|
|
93
|
-
const challenge = challengeBody.challenge ?? challengeBody.data?.challenge;
|
|
94
|
-
if (!challenge) {
|
|
95
|
-
throw new Error('the node issued no challenge');
|
|
96
|
-
}
|
|
97
|
-
const session = await generateSessionKey();
|
|
98
|
-
const issuedAt = Math.floor(Date.now() / 1000);
|
|
99
|
-
const statement = await signLoginStatement({
|
|
100
|
-
node: config.node,
|
|
101
|
-
audience: config.audience,
|
|
102
|
-
challenge,
|
|
103
|
-
sessionKey: session.publicKey,
|
|
104
|
-
issuedAt,
|
|
105
|
-
expiresAt: issuedAt + (config.ttlSeconds ?? DEFAULT_TTL_SECONDS),
|
|
106
|
-
// Resolved once and handed on, so a config carrying a secret and a config
|
|
107
|
-
// carrying a `CryptoKey` take exactly the same path from here down.
|
|
108
|
-
signer: await resolveSigner(config.deviceSecret, config.signer, 'deviceSecret'),
|
|
109
|
-
});
|
|
110
|
-
// `timestamp` is required and the request refuses unknown fields, so a body
|
|
111
|
-
// missing it is rejected during deserialization — before the provider runs,
|
|
112
|
-
// and with an error that names the request shape rather than the login.
|
|
113
|
-
//
|
|
114
|
-
// `permissions` is omitted, not empty: see the module note.
|
|
115
|
-
const tokenBody = (await request('/auth/token', {
|
|
116
|
-
method: 'POST',
|
|
117
|
-
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
118
|
-
body: JSON.stringify({
|
|
119
|
-
auth_method: 'account_proof',
|
|
120
|
-
public_key: session.publicKey,
|
|
121
|
-
client_name: config.clientName ?? baseUrl,
|
|
122
|
-
timestamp: issuedAt,
|
|
123
|
-
provider_data: {
|
|
124
|
-
challenge,
|
|
125
|
-
login_statement: statement,
|
|
126
|
-
account_proof: config.accountProof,
|
|
127
|
-
},
|
|
128
|
-
}),
|
|
129
|
-
}));
|
|
130
|
-
const accessToken = tokenBody.access_token ?? tokenBody.data?.access_token;
|
|
131
|
-
const refreshToken = tokenBody.refresh_token ?? tokenBody.data?.refresh_token;
|
|
132
|
-
if (!accessToken) {
|
|
133
|
-
throw new Error('the node minted no session');
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
accessToken,
|
|
137
|
-
refreshToken: refreshToken ?? '',
|
|
138
|
-
sessionKey: session.publicKey,
|
|
139
|
-
sessionSecret: session.secret,
|
|
140
|
-
};
|
|
141
|
-
}
|
package/dist/mero-js.d.ts
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import type { AuthApiClient } from './auth-api/index.js';
|
|
2
|
-
import type { AdminApiClient } from './admin-api/index.js';
|
|
3
|
-
import type { TokenStore } from './token-store/index.js';
|
|
4
|
-
import type { ProofRequest, ProofSignerOptions } from './request/index.js';
|
|
5
|
-
import type { AuthCallbackResult, AuthLoginOptions, ParseAuthCallbackOptions } from './auth/index.js';
|
|
6
|
-
import { RpcClient } from './rpc/index.js';
|
|
7
|
-
import { SseClient } from './events/sse.js';
|
|
8
|
-
import { WsClient } from './events/ws.js';
|
|
9
|
-
import { EphemeralClient } from './ephemeral/index.js';
|
|
10
|
-
import { CloudClient } from './cloud/cloud-client.js';
|
|
11
|
-
import type { CloudClientConfig } from './cloud/cloud-client.js';
|
|
12
|
-
export interface MeroJsConfig {
|
|
13
|
-
/** Base URL for the Calimero node */
|
|
14
|
-
baseUrl: string;
|
|
15
|
-
/** Initial credentials for authentication */
|
|
16
|
-
credentials?: {
|
|
17
|
-
username: string;
|
|
18
|
-
password: string;
|
|
19
|
-
};
|
|
20
|
-
/** Custom HTTP client timeout in milliseconds */
|
|
21
|
-
timeoutMs?: number;
|
|
22
|
-
/** Request credentials mode for fetch (omit, same-origin, include) */
|
|
23
|
-
requestCredentials?: RequestCredentials;
|
|
24
|
-
/** Custom fetch for every HTTP request (`auth`, `admin`, `rpc`, `events`). Defaults to global `fetch`. */
|
|
25
|
-
fetch?: typeof fetch;
|
|
26
|
-
/** Optional token store for persistence */
|
|
27
|
-
tokenStore?: TokenStore;
|
|
28
|
-
/**
|
|
29
|
-
* Called when the node reports that the credential family is gone
|
|
30
|
-
* (`x-auth-error: token_reuse` / `token_revoked`). Terminal: the tokens have
|
|
31
|
-
* already been cleared by the time this runs and nothing is retried, so use it
|
|
32
|
-
* to send the user back through login. Errors thrown here are swallowed —
|
|
33
|
-
* never let a UI failure mask the auth error.
|
|
34
|
-
*/
|
|
35
|
-
onAuthRevoked?: () => Promise<void> | void;
|
|
36
|
-
/**
|
|
37
|
-
* Calimero Cloud, reachable as `sdk.cloud`.
|
|
38
|
-
*
|
|
39
|
-
* A node connection and a cloud account are separate things a client can have
|
|
40
|
-
* either of, both of, or neither — a desktop app with a local node and a
|
|
41
|
-
* cloud subscription has both, and needs them from one object. So this is
|
|
42
|
-
* configuration on the existing SDK rather than a second SDK: pass the
|
|
43
|
-
* session token (or none, and sign in through `sdk.cloud`) and the node half
|
|
44
|
-
* is unaffected.
|
|
45
|
-
*
|
|
46
|
-
* For a caller with *no* node at all, `connectCloud` is the entry point
|
|
47
|
-
* instead — it returns a connection that can write without one.
|
|
48
|
-
*/
|
|
49
|
-
cloud?: CloudClientConfig;
|
|
50
|
-
/**
|
|
51
|
-
* Sign every request with a device key, instead of or alongside a session.
|
|
52
|
-
*
|
|
53
|
-
* A session is a bearer token: obtained once, presented many times. A
|
|
54
|
-
* request-carried proof commits to one method, one path and one body, so it
|
|
55
|
-
* is minted per call and cannot be lifted onto another request. It is what
|
|
56
|
-
* lets a client talk to a relay it has no account on — nothing was ever
|
|
57
|
-
* issued to it.
|
|
58
|
-
*
|
|
59
|
-
* Pass the keys and let the SDK mint each proof:
|
|
60
|
-
*
|
|
61
|
-
* ```ts
|
|
62
|
-
* new MeroJs({
|
|
63
|
-
* baseUrl,
|
|
64
|
-
* requestProof: { credential, session, signerSecret },
|
|
65
|
-
* });
|
|
66
|
-
* ```
|
|
67
|
-
*
|
|
68
|
-
* …or pass your own signer, when the key must not reach the SDK at all — a
|
|
69
|
-
* hardware token, or a worker that holds it:
|
|
70
|
-
*
|
|
71
|
-
* ```ts
|
|
72
|
-
* new MeroJs({ baseUrl, requestProof: (req) => myWorker.sign(req) });
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* The node only honours this when it runs with `--delegated-access`; a node
|
|
76
|
-
* that does not answers `403`, which is distinct from the `401` a bad proof
|
|
77
|
-
* gets.
|
|
78
|
-
*
|
|
79
|
-
* Applies to the request/response API. `events` (SSE) and `ws` are long-lived
|
|
80
|
-
* connections rather than requests, so a per-request signature does not
|
|
81
|
-
* describe them — they still use the session.
|
|
82
|
-
*/
|
|
83
|
-
requestProof?: ProofSignerOptions | ((request: ProofRequest) => Promise<string | undefined>);
|
|
84
|
-
}
|
|
85
|
-
export interface TokenData {
|
|
86
|
-
access_token: string;
|
|
87
|
-
refresh_token: string;
|
|
88
|
-
expires_at: number;
|
|
89
|
-
/** Origin and path prefix of the issuing node; a store entry for another node is ignored. */
|
|
90
|
-
node_origin?: string;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Main MeroJs SDK class that manages all API clients and authentication
|
|
94
|
-
*/
|
|
95
|
-
export declare class MeroJs {
|
|
96
|
-
private config;
|
|
97
|
-
private httpClient;
|
|
98
|
-
private authClient;
|
|
99
|
-
private adminClient;
|
|
100
|
-
private tokenData;
|
|
101
|
-
private refreshPromise;
|
|
102
|
-
private tokenStore;
|
|
103
|
-
private storeHoldsTokens;
|
|
104
|
-
private tokenGeneration;
|
|
105
|
-
private readonly onStorage;
|
|
106
|
-
private readonly nodeKey;
|
|
107
|
-
private rpcClient;
|
|
108
|
-
private sseClient;
|
|
109
|
-
private wsClient;
|
|
110
|
-
private wsWarned;
|
|
111
|
-
private ephemeralClient?;
|
|
112
|
-
private cloudClient?;
|
|
113
|
-
constructor(config: MeroJsConfig);
|
|
114
|
-
/**
|
|
115
|
-
* Get the Auth API client
|
|
116
|
-
*/
|
|
117
|
-
get auth(): AuthApiClient;
|
|
118
|
-
/**
|
|
119
|
-
* Get the Admin API client
|
|
120
|
-
*/
|
|
121
|
-
get admin(): AdminApiClient;
|
|
122
|
-
/**
|
|
123
|
-
* Get the RPC client (lazy initialized)
|
|
124
|
-
*/
|
|
125
|
-
get rpc(): RpcClient;
|
|
126
|
-
/**
|
|
127
|
-
* Get the SSE event client (lazy initialized)
|
|
128
|
-
*/
|
|
129
|
-
get events(): SseClient;
|
|
130
|
-
/**
|
|
131
|
-
* Get the ephemeral-presence client (lazy initialized).
|
|
132
|
-
*
|
|
133
|
-
* Shares this instance's SSE client, so `subscribe` reuses the one event
|
|
134
|
-
* stream rather than opening a second connection.
|
|
135
|
-
*/
|
|
136
|
-
get ephemeral(): EphemeralClient;
|
|
137
|
-
/**
|
|
138
|
-
* Calimero Cloud (lazy initialized).
|
|
139
|
-
*
|
|
140
|
-
* Available whether or not `cloud` was configured — an app that signs in
|
|
141
|
-
* later gets an unauthenticated client it can call `signInWithGoogle` on,
|
|
142
|
-
* which is one fewer construction path than making the getter conditional.
|
|
143
|
-
* It is entirely independent of this instance's node credential: the cloud
|
|
144
|
-
* knows nothing about the node's tokens and the node knows nothing about the
|
|
145
|
-
* cloud session.
|
|
146
|
-
*/
|
|
147
|
-
get cloud(): CloudClient;
|
|
148
|
-
/**
|
|
149
|
-
* Get the WebSocket event client (lazy initialized).
|
|
150
|
-
* @experimental Use `events` (SSE) for production. WsClient is experimental.
|
|
151
|
-
*/
|
|
152
|
-
get ws(): WsClient;
|
|
153
|
-
/**
|
|
154
|
-
* Authenticate with the provided credentials
|
|
155
|
-
* This will create the root key on first use
|
|
156
|
-
*/
|
|
157
|
-
authenticate(credentials?: {
|
|
158
|
-
username: string;
|
|
159
|
-
password: string;
|
|
160
|
-
}): Promise<TokenData>;
|
|
161
|
-
private persistTokens;
|
|
162
|
-
/** The stored bundle, only if this node issued it; a legacy or foreign entry reads as empty. */
|
|
163
|
-
private readStoredTokens;
|
|
164
|
-
private signedOutElsewhere;
|
|
165
|
-
private dropLocalTokens;
|
|
166
|
-
/**
|
|
167
|
-
* Get a valid token. Returns the current token as-is.
|
|
168
|
-
* The server rejects refresh attempts while the access token is still valid,
|
|
169
|
-
* so we never proactively refresh. Instead, the WebHttpClient handles 401
|
|
170
|
-
* responses reactively via the refreshToken transport hook.
|
|
171
|
-
*/
|
|
172
|
-
private getValidToken;
|
|
173
|
-
/**
|
|
174
|
-
* Refresh the access token. Single-flight: every caller (including the HTTP
|
|
175
|
-
* transport's 401 hook) goes through here.
|
|
176
|
-
*
|
|
177
|
-
* Refresh tokens are single-use (calimero-network/core#3083): each refresh
|
|
178
|
-
* consumes the presented token and returns a new one, and replaying a consumed
|
|
179
|
-
* token makes the server revoke the whole family. A refresh must therefore
|
|
180
|
-
* happen exactly once per rotation, which needs three layers:
|
|
181
|
-
* - an in-process promise, so concurrent 401s in this instance share one call;
|
|
182
|
-
* - a Web Lock (when available), so other tabs/webviews don't refresh at the
|
|
183
|
-
* same time on the same stored token;
|
|
184
|
-
* - a re-read of the token store inside the lock, so a bundle that another
|
|
185
|
-
* instance already rotated is adopted instead of replaying a stale token.
|
|
186
|
-
*/
|
|
187
|
-
private performTokenRefresh;
|
|
188
|
-
/**
|
|
189
|
-
* Run `fn` under the refresh lock: the token store's own (shared across
|
|
190
|
-
* processes), else the cross-tab Web Lock, else directly.
|
|
191
|
-
*/
|
|
192
|
-
private withRefreshLock;
|
|
193
|
-
/**
|
|
194
|
-
* Perform the actual token refresh. Runs with the refresh lock held.
|
|
195
|
-
*/
|
|
196
|
-
private performTokenRefreshLocked;
|
|
197
|
-
/**
|
|
198
|
-
* Clear the current token
|
|
199
|
-
*/
|
|
200
|
-
clearToken(): void;
|
|
201
|
-
/**
|
|
202
|
-
* Check if the SDK is authenticated
|
|
203
|
-
*/
|
|
204
|
-
isAuthenticated(): boolean;
|
|
205
|
-
/**
|
|
206
|
-
* Set token data directly (e.g., from auth callback).
|
|
207
|
-
* If `expires_at` is missing or 0, attempts to parse the JWT exp claim,
|
|
208
|
-
* falling back to 1 hour from now.
|
|
209
|
-
*/
|
|
210
|
-
setTokenData(data: TokenData): void;
|
|
211
|
-
/**
|
|
212
|
-
* Get the current token data (for debugging)
|
|
213
|
-
*/
|
|
214
|
-
getTokenData(): TokenData | null;
|
|
215
|
-
/**
|
|
216
|
-
* Close all event connections and clean up resources
|
|
217
|
-
*/
|
|
218
|
-
close(): void;
|
|
219
|
-
/**
|
|
220
|
-
* Parse an auth callback URL hash fragment (static utility)
|
|
221
|
-
*/
|
|
222
|
-
static parseAuthCallback(url: string, options?: ParseAuthCallbackOptions): AuthCallbackResult | null;
|
|
223
|
-
/**
|
|
224
|
-
* Build an auth login URL (static utility)
|
|
225
|
-
*/
|
|
226
|
-
static buildAuthLoginUrl(nodeUrl: string, opts: AuthLoginOptions): string;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Create a new MeroJs SDK instance
|
|
230
|
-
*/
|
|
231
|
-
export declare function createMeroJs(config: MeroJsConfig): MeroJs;
|