@calimero-network/mero-js 26.10.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 -12767
- 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 -12767
- 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 -686
- package/dist/admin-api/admin-client.js +0 -1225
- 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 -2041
- 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
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { type Signer } from '../signer/signer.js';
|
|
2
|
-
/** What a root scopes one device to. */
|
|
3
|
-
export interface DeviceScopeInput {
|
|
4
|
-
/**
|
|
5
|
-
* The account root's signing secret, 64 hex. Pass this or {@link signer}.
|
|
6
|
-
*/
|
|
7
|
-
rootSecret?: string;
|
|
8
|
-
/**
|
|
9
|
-
* The account root as a {@link Signer} — for a root that cannot be exported.
|
|
10
|
-
* Its `publicKey` is the genesis key the proof carries, and the account is
|
|
11
|
-
* derived from it.
|
|
12
|
-
*/
|
|
13
|
-
signer?: Signer;
|
|
14
|
-
/** The device being scoped, 64 hex — the one its certificate names. */
|
|
15
|
-
device: string;
|
|
16
|
-
/**
|
|
17
|
-
* Application ids the device may speak for, 64 hex each. **Empty means all of
|
|
18
|
-
* them**, which is also what the default is.
|
|
19
|
-
*
|
|
20
|
-
* A namespace binds the device only when its application is listed here (or
|
|
21
|
-
* the list is empty), so a scope naming the wrong application yields a relay
|
|
22
|
-
* refusal of `400`, not a binding.
|
|
23
|
-
*/
|
|
24
|
-
applications?: readonly string[];
|
|
25
|
-
/**
|
|
26
|
-
* Orders scopes for this device: only a higher one supersedes. 0 for a
|
|
27
|
-
* device's first scope.
|
|
28
|
-
*/
|
|
29
|
-
scopeEpoch?: number;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* The 32 bytes a root signs to scope a device: `domain_hash` over account,
|
|
33
|
-
* device, `scope_epoch` (u32 LE), `key_epoch` (u32 LE), then each application id
|
|
34
|
-
* as its own length-prefixed part.
|
|
35
|
-
*/
|
|
36
|
-
export declare function deviceScopePayload(input: {
|
|
37
|
-
account: string;
|
|
38
|
-
device: string;
|
|
39
|
-
applications: readonly string[];
|
|
40
|
-
scopeEpoch: number;
|
|
41
|
-
keyEpoch: number;
|
|
42
|
-
}): Promise<Uint8Array>;
|
|
43
|
-
/**
|
|
44
|
-
* Scope a device, returning the hex `AccountProof<DeviceScope>` a relay's
|
|
45
|
-
* `linkAccountDevice` takes beside the credential.
|
|
46
|
-
*
|
|
47
|
-
* ```
|
|
48
|
-
* AccountProof { genesis: AccountGenesis, chain: Vec<RootKeyHandoff>, statement: DeviceScope }
|
|
49
|
-
* AccountGenesis { version: u8, root_sign_pk: [u8; 32] }
|
|
50
|
-
* chain → u32-LE count (0 here)
|
|
51
|
-
* DeviceScope { account, device: [u8; 32] x2, applications: Vec<[u8; 32]>,
|
|
52
|
-
* scope_epoch: u32, key_epoch: u32, signature: [u8; 64] }
|
|
53
|
-
* ```
|
|
54
|
-
*
|
|
55
|
-
* `chain` is empty and `key_epoch` 0 for the reason they are in
|
|
56
|
-
* {@link signDeviceCert}: a root that was never handed off signs directly.
|
|
57
|
-
*/
|
|
58
|
-
export declare function signDeviceScope(input: DeviceScopeInput): Promise<string>;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Scoping a device offline: which applications a device of an account may speak
|
|
3
|
-
* for, signed by the account root.
|
|
4
|
-
*
|
|
5
|
-
* The certificate from {@link signDeviceCert} says *this key is a device of the
|
|
6
|
-
* account*. It does not say where: that is this statement, and a namespace binds
|
|
7
|
-
* a device only when both arrive together. A node that pairs a device signs the
|
|
8
|
-
* scope for you; an account with **no node** has to sign it itself, next to the
|
|
9
|
-
* certificate, and hand both to a relay's `linkAccountDevice`.
|
|
10
|
-
*
|
|
11
|
-
* Derived from core:
|
|
12
|
-
*
|
|
13
|
-
* - `DeviceScope` and `DeviceScope::signing_payload` — `crates/account/src/scope.rs`
|
|
14
|
-
* - `DEVICE_SCOPE_SIGN_DOMAIN` — `crates/account/src/domain.rs`
|
|
15
|
-
* - `AccountProof` / `AccountGenesis` borsh layout — `crates/account/src/{signed,account}.rs`
|
|
16
|
-
*
|
|
17
|
-
* The unit tests pin vectors produced by core's own `DeviceScope::sign`.
|
|
18
|
-
*/
|
|
19
|
-
import { concat, domainHash, fromHex, hex, u32le } from '../crypto/internal.js';
|
|
20
|
-
import { resolveSigner } from '../signer/signer.js';
|
|
21
|
-
import { accountForRootPublicKey, ACCOUNT_GENESIS_VERSION } from './device-cert.js';
|
|
22
|
-
const SCOPE_DOMAIN = new TextEncoder().encode('calimero.device.scope.v1');
|
|
23
|
-
/**
|
|
24
|
-
* The 32 bytes a root signs to scope a device: `domain_hash` over account,
|
|
25
|
-
* device, `scope_epoch` (u32 LE), `key_epoch` (u32 LE), then each application id
|
|
26
|
-
* as its own length-prefixed part.
|
|
27
|
-
*/
|
|
28
|
-
export async function deviceScopePayload(input) {
|
|
29
|
-
return domainHash(SCOPE_DOMAIN, [
|
|
30
|
-
fromHex(input.account, 'account', 32),
|
|
31
|
-
fromHex(input.device, 'device', 32),
|
|
32
|
-
u32le(input.scopeEpoch),
|
|
33
|
-
u32le(input.keyEpoch),
|
|
34
|
-
...input.applications.map((a, i) => fromHex(a, `applications[${i}]`, 32)),
|
|
35
|
-
]);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Scope a device, returning the hex `AccountProof<DeviceScope>` a relay's
|
|
39
|
-
* `linkAccountDevice` takes beside the credential.
|
|
40
|
-
*
|
|
41
|
-
* ```
|
|
42
|
-
* AccountProof { genesis: AccountGenesis, chain: Vec<RootKeyHandoff>, statement: DeviceScope }
|
|
43
|
-
* AccountGenesis { version: u8, root_sign_pk: [u8; 32] }
|
|
44
|
-
* chain → u32-LE count (0 here)
|
|
45
|
-
* DeviceScope { account, device: [u8; 32] x2, applications: Vec<[u8; 32]>,
|
|
46
|
-
* scope_epoch: u32, key_epoch: u32, signature: [u8; 64] }
|
|
47
|
-
* ```
|
|
48
|
-
*
|
|
49
|
-
* `chain` is empty and `key_epoch` 0 for the reason they are in
|
|
50
|
-
* {@link signDeviceCert}: a root that was never handed off signs directly.
|
|
51
|
-
*/
|
|
52
|
-
export async function signDeviceScope(input) {
|
|
53
|
-
const signer = await resolveSigner(input.rootSecret, input.signer, 'rootSecret');
|
|
54
|
-
const rootPublicKey = fromHex(signer.publicKey, 'signer.publicKey', 32);
|
|
55
|
-
const account = await accountForRootPublicKey(hex(rootPublicKey));
|
|
56
|
-
const applications = input.applications ?? [];
|
|
57
|
-
const scopeEpoch = input.scopeEpoch ?? 0;
|
|
58
|
-
// `u32le` would wrap a negative or oversized value into a different epoch
|
|
59
|
-
// rather than refuse it, and the scope would then order itself wrongly.
|
|
60
|
-
if (!Number.isInteger(scopeEpoch) || scopeEpoch < 0 || scopeEpoch > 4294967295) {
|
|
61
|
-
throw new Error(`scopeEpoch must be a u32, got ${scopeEpoch}`);
|
|
62
|
-
}
|
|
63
|
-
const keyEpoch = 0;
|
|
64
|
-
const payload = await deviceScopePayload({
|
|
65
|
-
account,
|
|
66
|
-
device: input.device,
|
|
67
|
-
applications,
|
|
68
|
-
scopeEpoch,
|
|
69
|
-
keyEpoch,
|
|
70
|
-
});
|
|
71
|
-
const signature = await signer.sign(payload);
|
|
72
|
-
if (signature.length !== 64) {
|
|
73
|
-
throw new Error(`signer returned ${signature.length} bytes, expected a 64-byte Ed25519 signature`);
|
|
74
|
-
}
|
|
75
|
-
return hex(concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey, u32le(0), fromHex(account, 'account', 32), fromHex(input.device, 'device', 32), u32le(applications.length), ...applications.map((a, i) => fromHex(a, `applications[${i}]`, 32)), u32le(scopeEpoch), u32le(keyEpoch), signature));
|
|
76
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, accountForRootPublicKey, accountProofBytes, parseDeviceCredential, verifyDeviceCredential, } from './device-cert.js';
|
|
2
|
-
export type { DeviceCertInput, DeviceCredential } from './device-cert.js';
|
|
3
|
-
export { signDeviceScope, deviceScopePayload } from './device-scope.js';
|
|
4
|
-
export type { DeviceScopeInput } from './device-scope.js';
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// Offline device certification — the account-root half of the keyholder story.
|
|
2
|
-
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, accountForRootPublicKey, accountProofBytes, parseDeviceCredential, verifyDeviceCredential, } from './device-cert.js';
|
|
3
|
-
export { signDeviceScope, deviceScopePayload } from './device-scope.js';
|
package/dist/ephemeral/codec.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/** Default codec: JSON text as a byte array. The wire carries `state` as
|
|
2
|
-
* `number[]`, not a string, so this encodes to bytes rather than to text. */
|
|
3
|
-
export function jsonCodec() {
|
|
4
|
-
return {
|
|
5
|
-
encode(value) {
|
|
6
|
-
return Array.from(new TextEncoder().encode(JSON.stringify(value)));
|
|
7
|
-
},
|
|
8
|
-
decode(bytes) {
|
|
9
|
-
return JSON.parse(new TextDecoder().decode(new Uint8Array(bytes)));
|
|
10
|
-
},
|
|
11
|
-
};
|
|
12
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { HttpClient } from '../http-client/index.js';
|
|
2
|
-
import type { SseClient } from '../events/index.js';
|
|
3
|
-
import { jsonCodec } from './codec.js';
|
|
4
|
-
import type { Codec, EphemeralEntry } from './types.js';
|
|
5
|
-
export { jsonCodec };
|
|
6
|
-
export type { Codec, EphemeralEntry };
|
|
7
|
-
/**
|
|
8
|
-
* Ephemeral presence: transient, encrypted, never-persisted state (cursors,
|
|
9
|
-
* typing, presence) that gossips between nodes without a WASM run or DAG
|
|
10
|
-
* growth.
|
|
11
|
-
*
|
|
12
|
-
* The write/read asymmetry is the model, not an oversight. `set` takes no
|
|
13
|
-
* author: you can only ever write your OWN slot, and the node resolves the
|
|
14
|
-
* author server-side from its owned context identity — which is also why a
|
|
15
|
-
* client cannot publish as somebody else. `subscribe` returns everyone's
|
|
16
|
-
* slots, so each carries its `author`. The store is N independent
|
|
17
|
-
* single-writer registers keyed by author; there is no merge across authors.
|
|
18
|
-
*
|
|
19
|
-
* There is a single read path: `subscribe`. On subscribing to a context, the
|
|
20
|
-
* node replays that context's current presence to this connection as
|
|
21
|
-
* ordinary `Ephemeral` events (carrying `ageMs`), before any live deltas
|
|
22
|
-
* (which carry no `ageMs`). There is no separate snapshot RPC.
|
|
23
|
-
*/
|
|
24
|
-
export declare class EphemeralClient {
|
|
25
|
-
private httpClient;
|
|
26
|
-
private sse;
|
|
27
|
-
constructor(opts: {
|
|
28
|
-
httpClient: HttpClient;
|
|
29
|
-
sse: SseClient;
|
|
30
|
-
});
|
|
31
|
-
/**
|
|
32
|
-
* Publish your own presence slice, replacing it wholesale.
|
|
33
|
-
*
|
|
34
|
-
* Rejects with an `RpcError` (not a bare `Error`), so a typed failure such as
|
|
35
|
-
* an oversized slice keeps its `type` and `data` — e.g. `SliceTooLarge` with
|
|
36
|
-
* the offending size — and is `instanceof RpcError` like every other RPC in
|
|
37
|
-
* this SDK.
|
|
38
|
-
*/
|
|
39
|
-
set<T>(contextId: string, state: T, codec?: Codec<T>): Promise<void>;
|
|
40
|
-
/**
|
|
41
|
-
* Observe presence changes for a context.
|
|
42
|
-
*
|
|
43
|
-
* This adds NO transport — it is a typed filter over the existing SSE event
|
|
44
|
-
* stream, which already carries `{ contextId, type, data }`. On subscribing,
|
|
45
|
-
* the node replays that context's current presence to this connection as
|
|
46
|
-
* ordinary `Ephemeral` events before any live deltas; a replayed entry
|
|
47
|
-
* carries `ageMs`, a live delta does not (never synthesized as `0` — absent
|
|
48
|
-
* and zero mean different things). Returns an unsubscribe function.
|
|
49
|
-
*/
|
|
50
|
-
subscribe<T>(contextId: string, handler: (entry: EphemeralEntry<T>) => void, codec?: Codec<T>): () => void;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Presence for one context off an event stream: a typed filter over the SSE
|
|
54
|
-
* events that already carry `{ contextId, type, data }`. Shared by a node
|
|
55
|
-
* client and an account's relay client, which read presence the same way.
|
|
56
|
-
*/
|
|
57
|
-
export declare function subscribePresence<T>(sse: SseClient, contextId: string, handler: (entry: EphemeralEntry<T>) => void, codec?: Codec<T>): () => void;
|
package/dist/ephemeral/index.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { jsonRpcCall } from '../rpc/index.js';
|
|
2
|
-
import { jsonCodec } from './codec.js';
|
|
3
|
-
export { jsonCodec };
|
|
4
|
-
/**
|
|
5
|
-
* Ephemeral presence: transient, encrypted, never-persisted state (cursors,
|
|
6
|
-
* typing, presence) that gossips between nodes without a WASM run or DAG
|
|
7
|
-
* growth.
|
|
8
|
-
*
|
|
9
|
-
* The write/read asymmetry is the model, not an oversight. `set` takes no
|
|
10
|
-
* author: you can only ever write your OWN slot, and the node resolves the
|
|
11
|
-
* author server-side from its owned context identity — which is also why a
|
|
12
|
-
* client cannot publish as somebody else. `subscribe` returns everyone's
|
|
13
|
-
* slots, so each carries its `author`. The store is N independent
|
|
14
|
-
* single-writer registers keyed by author; there is no merge across authors.
|
|
15
|
-
*
|
|
16
|
-
* There is a single read path: `subscribe`. On subscribing to a context, the
|
|
17
|
-
* node replays that context's current presence to this connection as
|
|
18
|
-
* ordinary `Ephemeral` events (carrying `ageMs`), before any live deltas
|
|
19
|
-
* (which carry no `ageMs`). There is no separate snapshot RPC.
|
|
20
|
-
*/
|
|
21
|
-
export class EphemeralClient {
|
|
22
|
-
constructor(opts) {
|
|
23
|
-
this.httpClient = opts.httpClient;
|
|
24
|
-
this.sse = opts.sse;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Publish your own presence slice, replacing it wholesale.
|
|
28
|
-
*
|
|
29
|
-
* Rejects with an `RpcError` (not a bare `Error`), so a typed failure such as
|
|
30
|
-
* an oversized slice keeps its `type` and `data` — e.g. `SliceTooLarge` with
|
|
31
|
-
* the offending size — and is `instanceof RpcError` like every other RPC in
|
|
32
|
-
* this SDK.
|
|
33
|
-
*/
|
|
34
|
-
async set(contextId, state, codec = jsonCodec()) {
|
|
35
|
-
await jsonRpcCall(this.httpClient, 'set_ephemeral', {
|
|
36
|
-
contextId,
|
|
37
|
-
state: codec.encode(state),
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Observe presence changes for a context.
|
|
42
|
-
*
|
|
43
|
-
* This adds NO transport — it is a typed filter over the existing SSE event
|
|
44
|
-
* stream, which already carries `{ contextId, type, data }`. On subscribing,
|
|
45
|
-
* the node replays that context's current presence to this connection as
|
|
46
|
-
* ordinary `Ephemeral` events before any live deltas; a replayed entry
|
|
47
|
-
* carries `ageMs`, a live delta does not (never synthesized as `0` — absent
|
|
48
|
-
* and zero mean different things). Returns an unsubscribe function.
|
|
49
|
-
*/
|
|
50
|
-
subscribe(contextId, handler, codec = jsonCodec()) {
|
|
51
|
-
return subscribePresence(this.sse, contextId, handler, codec);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Presence for one context off an event stream: a typed filter over the SSE
|
|
56
|
-
* events that already carry `{ contextId, type, data }`. Shared by a node
|
|
57
|
-
* client and an account's relay client, which read presence the same way.
|
|
58
|
-
*/
|
|
59
|
-
export function subscribePresence(sse, contextId, handler, codec = jsonCodec()) {
|
|
60
|
-
const listener = (event) => {
|
|
61
|
-
const e = event;
|
|
62
|
-
if (e.type !== 'Ephemeral' || e.contextId !== contextId)
|
|
63
|
-
return;
|
|
64
|
-
const data = e.data;
|
|
65
|
-
if (!data?.author)
|
|
66
|
-
return;
|
|
67
|
-
// `removed` is omitted on an upsert, so normalize to a boolean here and
|
|
68
|
-
// spare every caller the truthiness rule.
|
|
69
|
-
const removed = Boolean(data.removed);
|
|
70
|
-
const entry = {
|
|
71
|
-
author: data.author,
|
|
72
|
-
state: removed || data.state === undefined ? undefined : codec.decode(data.state),
|
|
73
|
-
removed,
|
|
74
|
-
};
|
|
75
|
-
// `ageMs` is present only on a replayed seed entry; pass it through as-is
|
|
76
|
-
// rather than defaulting a live delta to 0.
|
|
77
|
-
if (data.ageMs !== undefined)
|
|
78
|
-
entry.ageMs = data.ageMs;
|
|
79
|
-
if (data.account !== undefined)
|
|
80
|
-
entry.account = data.account;
|
|
81
|
-
handler(entry);
|
|
82
|
-
};
|
|
83
|
-
sse.on('event', listener);
|
|
84
|
-
// On a context this connection already holds, the node's one-time replay
|
|
85
|
-
// went to whichever listener came first: seed this one from what the
|
|
86
|
-
// client has kept, as the replay would have. (A context not held yet is
|
|
87
|
-
// replayed by the node on the subscribe below.) Optional: a test double
|
|
88
|
-
// or another event source may not keep presence.
|
|
89
|
-
if (sse.isSubscribed?.(contextId)) {
|
|
90
|
-
for (const data of sse.presenceSeed?.(contextId) ?? []) {
|
|
91
|
-
listener({ contextId, type: 'Ephemeral', data });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// Errors surface via the SSE client's own 'error' event; nothing more to
|
|
95
|
-
// do with them here.
|
|
96
|
-
void sse.connect().catch(() => undefined);
|
|
97
|
-
void sse.subscribe([contextId]).catch(() => undefined);
|
|
98
|
-
return () => {
|
|
99
|
-
sse.off('event', listener);
|
|
100
|
-
};
|
|
101
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/** Encoding for a presence slice. The node never deserializes it — the wire
|
|
2
|
-
* encoding is chosen client-side and travels client-to-client. */
|
|
3
|
-
export interface Codec<T> {
|
|
4
|
-
encode(value: T): number[];
|
|
5
|
-
decode(bytes: number[]): T;
|
|
6
|
-
}
|
|
7
|
-
/** One entry from `subscribe`. `state` is absent on a removal; `removed` is
|
|
8
|
-
* ABSENT (not false) on an upsert.
|
|
9
|
-
*
|
|
10
|
-
* On subscribing to a context, the node replays that context's current
|
|
11
|
-
* presence to this connection as ordinary `Ephemeral` events (same shape as a
|
|
12
|
-
* live delta), before any live deltas. `ageMs` distinguishes a replayed seed
|
|
13
|
-
* entry from a live one: it is ABSENT on a live delta (fresh at receipt) and
|
|
14
|
-
* PRESENT on a replayed entry, giving milliseconds since that author was last
|
|
15
|
-
* heard from, measured on the node. Relative, so no clock agreement between
|
|
16
|
-
* machines is needed. Bounded above by the node's 7s presence TTL. */
|
|
17
|
-
export interface EphemeralEntry<T> {
|
|
18
|
-
author: string;
|
|
19
|
-
/**
|
|
20
|
-
* The account a relay-carried update's device certificate names, hex. Absent
|
|
21
|
-
* for a node's own presence.
|
|
22
|
-
*/
|
|
23
|
-
account?: string;
|
|
24
|
-
state?: T;
|
|
25
|
-
removed?: boolean;
|
|
26
|
-
ageMs?: number;
|
|
27
|
-
}
|
package/dist/ephemeral/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/** The kind of failure, as far as it decides what the caller does next. */
|
|
2
|
-
export type ErrorKind =
|
|
3
|
-
/** 400. The request is wrong; sending it again cannot help. */
|
|
4
|
-
'invalid'
|
|
5
|
-
/** 401. This client's session lapsed; signing in again can finish it. */
|
|
6
|
-
| 'unauthorized'
|
|
7
|
-
/** 403. The node will not do this for this caller. */
|
|
8
|
-
| 'forbidden'
|
|
9
|
-
/** 404. What the request names does not exist on this node (yet). */
|
|
10
|
-
| 'not-found'
|
|
11
|
-
/** 409. The request contradicts the current state: expired, spent, removed. */
|
|
12
|
-
| 'conflict'
|
|
13
|
-
/** 410. It existed and is gone for good. */
|
|
14
|
-
| 'gone'
|
|
15
|
-
/** 413. The body is over the node's limit. */
|
|
16
|
-
| 'too-large'
|
|
17
|
-
/** 429. The node asked the caller to slow down. */
|
|
18
|
-
| 'rate-limited'
|
|
19
|
-
/** 503 or 504. The node cannot serve this yet — no peer online, say. */
|
|
20
|
-
| 'unavailable'
|
|
21
|
-
/** Any other 5xx. The node failed; the request may well have been fine. */
|
|
22
|
-
| 'server'
|
|
23
|
-
/** Status 0. The request never reached the node: offline, CORS, a timeout. */
|
|
24
|
-
| 'unreachable'
|
|
25
|
-
/** Not an HTTP failure, or one with nothing more specific to go on. */
|
|
26
|
-
| 'unknown';
|
|
27
|
-
export interface ClassifiedError {
|
|
28
|
-
kind: ErrorKind;
|
|
29
|
-
/** The HTTP status, when the error carries one. 0 means no response. */
|
|
30
|
-
status: number | undefined;
|
|
31
|
-
/**
|
|
32
|
-
* Whether the same request could succeed later without anything changing on
|
|
33
|
-
* the caller's side. False for a refusal the node chose — asking again gets
|
|
34
|
-
* the same answer — and true for a failure about the moment.
|
|
35
|
-
*/
|
|
36
|
-
retryable: boolean;
|
|
37
|
-
/**
|
|
38
|
-
* The node's own explanation, without an `HTTP <status>` prefix, falling back
|
|
39
|
-
* to the error's message. For logs and for a UI that shows detail; a UI that
|
|
40
|
-
* wants friendly copy should switch on `kind`.
|
|
41
|
-
*/
|
|
42
|
-
message: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* The HTTP status an error carries, in any shape a client throws: mero-js's
|
|
46
|
-
* `HTTPError.status`, an axios-style `response.status`, or a bare `statusCode`.
|
|
47
|
-
* Undefined when there is none — a thrown string, or an error raised before the
|
|
48
|
-
* request was sent.
|
|
49
|
-
*/
|
|
50
|
-
export declare function statusOf(err: unknown): number | undefined;
|
|
51
|
-
/**
|
|
52
|
-
* The most specific human-readable explanation an error carries, or
|
|
53
|
-
* `fallback`. Prefers the node's words (`HTTPError.explanation`, or an axios
|
|
54
|
-
* body's `error`/`message`) over a message that repeats the status line.
|
|
55
|
-
*/
|
|
56
|
-
export declare function messageOf(err: unknown, fallback?: string): string;
|
|
57
|
-
/**
|
|
58
|
-
* What a failed request means: its kind, whether a later attempt could work,
|
|
59
|
-
* and the node's own words for it.
|
|
60
|
-
*
|
|
61
|
-
* Accepts anything a `catch` hands over. A browser `fetch` that could not
|
|
62
|
-
* connect throws a `TypeError`, which is read as `unreachable` like mero-js's
|
|
63
|
-
* own status-0 `HTTPError`.
|
|
64
|
-
*/
|
|
65
|
-
export declare function classifyError(err: unknown): ClassifiedError;
|
package/dist/errors/classify.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { RelayLoginError } from '../account/relay-login-error.js';
|
|
2
|
-
const RETRYABLE = {
|
|
3
|
-
invalid: false,
|
|
4
|
-
// The session, not the request: signing in again and repeating it works.
|
|
5
|
-
unauthorized: true,
|
|
6
|
-
forbidden: false,
|
|
7
|
-
// Too broad to give up on — the resource may simply not have synced yet.
|
|
8
|
-
'not-found': true,
|
|
9
|
-
conflict: false,
|
|
10
|
-
gone: false,
|
|
11
|
-
'too-large': false,
|
|
12
|
-
'rate-limited': true,
|
|
13
|
-
unavailable: true,
|
|
14
|
-
server: true,
|
|
15
|
-
unreachable: true,
|
|
16
|
-
unknown: true,
|
|
17
|
-
};
|
|
18
|
-
function kindForStatus(status) {
|
|
19
|
-
switch (status) {
|
|
20
|
-
case 0:
|
|
21
|
-
return 'unreachable';
|
|
22
|
-
case 400:
|
|
23
|
-
return 'invalid';
|
|
24
|
-
case 401:
|
|
25
|
-
return 'unauthorized';
|
|
26
|
-
case 403:
|
|
27
|
-
return 'forbidden';
|
|
28
|
-
case 404:
|
|
29
|
-
return 'not-found';
|
|
30
|
-
case 409:
|
|
31
|
-
return 'conflict';
|
|
32
|
-
case 410:
|
|
33
|
-
return 'gone';
|
|
34
|
-
case 413:
|
|
35
|
-
return 'too-large';
|
|
36
|
-
case 429:
|
|
37
|
-
return 'rate-limited';
|
|
38
|
-
case 503:
|
|
39
|
-
case 504:
|
|
40
|
-
return 'unavailable';
|
|
41
|
-
}
|
|
42
|
-
if (status >= 500 && status < 600)
|
|
43
|
-
return 'server';
|
|
44
|
-
if (status >= 400 && status < 500)
|
|
45
|
-
return 'invalid';
|
|
46
|
-
return 'unknown';
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* The HTTP status an error carries, in any shape a client throws: mero-js's
|
|
50
|
-
* `HTTPError.status`, an axios-style `response.status`, or a bare `statusCode`.
|
|
51
|
-
* Undefined when there is none — a thrown string, or an error raised before the
|
|
52
|
-
* request was sent.
|
|
53
|
-
*/
|
|
54
|
-
export function statusOf(err) {
|
|
55
|
-
if (!err || typeof err !== 'object')
|
|
56
|
-
return undefined;
|
|
57
|
-
const shaped = err;
|
|
58
|
-
for (const candidate of [shaped.status, shaped.response?.status, shaped.statusCode]) {
|
|
59
|
-
if (typeof candidate === 'number' && Number.isFinite(candidate))
|
|
60
|
-
return candidate;
|
|
61
|
-
}
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* The most specific human-readable explanation an error carries, or
|
|
66
|
-
* `fallback`. Prefers the node's words (`HTTPError.explanation`, or an axios
|
|
67
|
-
* body's `error`/`message`) over a message that repeats the status line.
|
|
68
|
-
*/
|
|
69
|
-
export function messageOf(err, fallback = 'Request failed') {
|
|
70
|
-
if (typeof err === 'string')
|
|
71
|
-
return err.trim() || fallback;
|
|
72
|
-
if (!err || typeof err !== 'object')
|
|
73
|
-
return fallback;
|
|
74
|
-
const shaped = err;
|
|
75
|
-
for (const candidate of [
|
|
76
|
-
shaped.explanation,
|
|
77
|
-
shaped.response?.data?.error,
|
|
78
|
-
shaped.response?.data?.message,
|
|
79
|
-
shaped.data?.message,
|
|
80
|
-
shaped.error,
|
|
81
|
-
shaped.message,
|
|
82
|
-
]) {
|
|
83
|
-
if (typeof candidate === 'string' && candidate.trim())
|
|
84
|
-
return candidate;
|
|
85
|
-
}
|
|
86
|
-
return fallback;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* What a failed request means: its kind, whether a later attempt could work,
|
|
90
|
-
* and the node's own words for it.
|
|
91
|
-
*
|
|
92
|
-
* Accepts anything a `catch` hands over. A browser `fetch` that could not
|
|
93
|
-
* connect throws a `TypeError`, which is read as `unreachable` like mero-js's
|
|
94
|
-
* own status-0 `HTTPError`.
|
|
95
|
-
*/
|
|
96
|
-
export function classifyError(err) {
|
|
97
|
-
// A relay login that failed before the request was sent: its own status is
|
|
98
|
-
// about the login, so it is read by what it means for the request — a
|
|
99
|
-
// refused credential is this client's session, anything else the relay's.
|
|
100
|
-
if (err instanceof RelayLoginError) {
|
|
101
|
-
const status = err.loginStatus;
|
|
102
|
-
const kind = err.kind === 'signed-out' ? 'unauthorized' : status ? kindForStatus(status) : 'unreachable';
|
|
103
|
-
return { kind, status, retryable: RETRYABLE[kind], message: messageOf(err) };
|
|
104
|
-
}
|
|
105
|
-
const status = statusOf(err);
|
|
106
|
-
let kind;
|
|
107
|
-
if (status !== undefined) {
|
|
108
|
-
kind = kindForStatus(status);
|
|
109
|
-
}
|
|
110
|
-
else if (err instanceof TypeError) {
|
|
111
|
-
kind = 'unreachable';
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
kind = 'unknown';
|
|
115
|
-
}
|
|
116
|
-
return { kind, status, retryable: RETRYABLE[kind], message: messageOf(err) };
|
|
117
|
-
}
|
package/dist/errors/index.d.ts
DELETED
package/dist/errors/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { classifyError } from './classify.js';
|
package/dist/events/group.d.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import type { GroupMemberRole } from '../admin-api/admin-types.js';
|
|
2
|
-
/** Parsed group-membership event (core's untagged `NodeEvent` group variant). */
|
|
3
|
-
export interface GroupMembershipEventData {
|
|
4
|
-
groupId: string;
|
|
5
|
-
type: 'MemberJoined' | 'MemberAdded' | 'MemberRemoved';
|
|
6
|
-
data: {
|
|
7
|
-
/** The member's ACCOUNT, hex-encoded 32 bytes (64 chars) - the principal the
|
|
8
|
-
* governance rows name. Not a signing key: the field this replaced
|
|
9
|
-
* carried one, and both are strings, so the rename is what makes a stale
|
|
10
|
-
* consumer fail loudly instead of comparing accounts against keys forever. */
|
|
11
|
-
memberAccount: string;
|
|
12
|
-
/** Absent on `MemberRemoved`, and on a `MemberJoined` inherited from an Open
|
|
13
|
-
* subgroup. Core's set is closed. */
|
|
14
|
-
role?: GroupMemberRole;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* A migration was accepted and its target ABI state version resolved.
|
|
19
|
-
* `toStateVersion` is the `#[app::state(version = N)]` number, not the bundle
|
|
20
|
-
* semver (`toVersion`).
|
|
21
|
-
*/
|
|
22
|
-
export interface MigrationStartedData {
|
|
23
|
-
fromVersion: string;
|
|
24
|
-
toVersion: string;
|
|
25
|
-
toStateVersion: number;
|
|
26
|
-
/** Contexts the EMITTING NODE enumerated for the migration. Node-local, never
|
|
27
|
-
* the fleet cohort size that `MigrationProgressData.total` carries. */
|
|
28
|
-
localContextsTotal: number;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Fleet rollup counters, recomputed as peers' heartbeat facts change. Counters
|
|
32
|
-
* only: the per-member detail behind them stays in the admin-gated
|
|
33
|
-
* `getMigrationStatus` read.
|
|
34
|
-
*/
|
|
35
|
-
export interface MigrationProgressData {
|
|
36
|
-
migrated: number;
|
|
37
|
-
inProgress: number;
|
|
38
|
-
unknown: number;
|
|
39
|
-
failed: number;
|
|
40
|
-
/** The pinned FLEET COHORT size, never a node-local context count like
|
|
41
|
-
* `MigrationStartedData.localContextsTotal`. */
|
|
42
|
-
total: number;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* One subgroup's local context swaps advanced on the emitting node.
|
|
46
|
-
*
|
|
47
|
-
* Admin-only: it names a descendant subgroup, which a plain namespace member
|
|
48
|
-
* may not enumerate, so core withholds it from non-admin subscribers. A
|
|
49
|
-
* non-admin never receiving this variant is correct behaviour, not a gap.
|
|
50
|
-
*/
|
|
51
|
-
export interface CascadeProgressData {
|
|
52
|
-
/** Hex-encoded descendant subgroup id, never the namespace root the event is
|
|
53
|
-
* keyed on. */
|
|
54
|
-
subgroupId: string;
|
|
55
|
-
localContextsSwapped: number;
|
|
56
|
-
/** Contexts the emitting node holds for THIS SUBGROUP. Node-local and
|
|
57
|
-
* per-subgroup; unrelated to both sibling totals. */
|
|
58
|
-
localContextsTotal: number;
|
|
59
|
-
}
|
|
60
|
-
/** Every pinned-cohort member reported the target version. */
|
|
61
|
-
export interface MigrationCompletedData {
|
|
62
|
-
toVersion: string;
|
|
63
|
-
/** FLEET convergence, in seconds since the epoch: the same stamp
|
|
64
|
-
* `MigrationStatus.fleetCompletedAt` returns. Not `GroupUpgradeStatus.completedAt`,
|
|
65
|
-
* which is this node's own local swap completion. */
|
|
66
|
-
completedAt: number;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Parsed group-migration event (core's `GroupMigration` `NodeEvent` variant),
|
|
70
|
-
* keyed on the namespace root a client subscribes with.
|
|
71
|
-
*
|
|
72
|
-
* `MigrationStarted`, `MigrationProgress` and `MigrationCompleted` reach every
|
|
73
|
-
* subscribed member; `CascadeProgress` reaches namespace admins only.
|
|
74
|
-
*/
|
|
75
|
-
export type GroupMigrationEventData = {
|
|
76
|
-
groupId: string;
|
|
77
|
-
type: 'MigrationStarted';
|
|
78
|
-
data: MigrationStartedData;
|
|
79
|
-
} | {
|
|
80
|
-
groupId: string;
|
|
81
|
-
type: 'MigrationProgress';
|
|
82
|
-
data: MigrationProgressData;
|
|
83
|
-
} | {
|
|
84
|
-
groupId: string;
|
|
85
|
-
type: 'CascadeProgress';
|
|
86
|
-
data: CascadeProgressData;
|
|
87
|
-
} | {
|
|
88
|
-
groupId: string;
|
|
89
|
-
type: 'MigrationCompleted';
|
|
90
|
-
data: MigrationCompletedData;
|
|
91
|
-
};
|
|
92
|
-
/** Narrows a raw `'event'` payload to the group-migration family by its tag. */
|
|
93
|
-
export declare function isGroupMigrationEvent(event: {
|
|
94
|
-
type?: string;
|
|
95
|
-
}): event is GroupMigrationEventData;
|
package/dist/events/group.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
const MIGRATION_EVENT_TYPES = new Set([
|
|
2
|
-
'MigrationStarted',
|
|
3
|
-
'MigrationProgress',
|
|
4
|
-
'CascadeProgress',
|
|
5
|
-
'MigrationCompleted',
|
|
6
|
-
]);
|
|
7
|
-
/** Narrows a raw `'event'` payload to the group-migration family by its tag. */
|
|
8
|
-
export function isGroupMigrationEvent(event) {
|
|
9
|
-
return event.type !== undefined && MIGRATION_EVENT_TYPES.has(event.type);
|
|
10
|
-
}
|
package/dist/events/index.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { SseClient } from './sse.js';
|
|
2
|
-
export type { SseEventData, AppVersionChangedEvent } from './sse.js';
|
|
3
|
-
export { WsClient } from './ws.js';
|
|
4
|
-
export type { WsEventData } from './ws.js';
|
|
5
|
-
export type { GroupMembershipEventData, GroupMigrationEventData, MigrationStartedData, MigrationProgressData, CascadeProgressData, MigrationCompletedData, } from './group.js';
|
package/dist/events/index.js
DELETED