@holochain/client 0.21.0-dev.1 → 0.21.0-dev.3
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/lib/api/admin/types.d.ts
CHANGED
|
@@ -976,18 +976,14 @@ export interface TransportConnectionStats {
|
|
|
976
976
|
*/
|
|
977
977
|
opened_at_s: number;
|
|
978
978
|
/**
|
|
979
|
-
* True if this connection has successfully upgraded to
|
|
979
|
+
* True if this connection has successfully upgraded to a direct connection.
|
|
980
980
|
*/
|
|
981
|
-
|
|
981
|
+
is_direct: boolean;
|
|
982
982
|
}
|
|
983
983
|
/**
|
|
984
984
|
* @public
|
|
985
985
|
*/
|
|
986
986
|
export type DumpNetworkStatsResponse = ApiTransportStats;
|
|
987
|
-
/**
|
|
988
|
-
* @public
|
|
989
|
-
*/
|
|
990
|
-
export type AppDumpNetworkStatsResponse = TransportStats;
|
|
991
987
|
/**
|
|
992
988
|
* Arguments for dumping network metrics.
|
|
993
989
|
*
|
package/lib/api/app/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UnsubscribeFunction } from "emittery";
|
|
2
|
-
import { AgentPubKey, AppAuthenticationToken, AppInfo, CapSecret, CellId, ClonedCell, DnaHash, DnaProperties, EntryHash, FunctionName, InstalledAppId, MembraneProof, MemproofMap, NetworkSeed, Nonce256Bit, RoleName, Timestamp, Transformer, WebsocketConnectionOptions, ZomeName, PreflightRequest, SignedAction, SignedActionHashed,
|
|
2
|
+
import { AgentPubKey, AppAuthenticationToken, AppInfo, CapSecret, CellId, ClonedCell, DnaHash, DnaProperties, EntryHash, FunctionName, InstalledAppId, MembraneProof, MemproofMap, NetworkSeed, Nonce256Bit, RoleName, Timestamp, Transformer, WebsocketConnectionOptions, ZomeName, PreflightRequest, SignedAction, SignedActionHashed, DumpNetworkMetricsResponse, DumpNetworkMetricsRequest, DumpNetworkStatsResponse } from "../../index.js";
|
|
3
3
|
/**
|
|
4
4
|
* @public
|
|
5
5
|
*/
|
|
@@ -407,7 +407,7 @@ export interface AppClient {
|
|
|
407
407
|
appInfo(): Promise<AppInfoResponse>;
|
|
408
408
|
myPubKey: AgentPubKey;
|
|
409
409
|
installedAppId: InstalledAppId;
|
|
410
|
-
dumpNetworkStats(): Promise<
|
|
410
|
+
dumpNetworkStats(): Promise<DumpNetworkStatsResponse>;
|
|
411
411
|
dumpNetworkMetrics(args: DumpNetworkMetricsRequest): Promise<DumpNetworkMetricsResponse>;
|
|
412
412
|
createCloneCell(args: CreateCloneCellRequest): Promise<CreateCloneCellResponse>;
|
|
413
413
|
enableCloneCell(args: EnableCloneCellRequest): Promise<EnableCloneCellResponse>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UnsubscribeFunction } from "emittery";
|
|
2
2
|
import { AgentPubKey, InstalledAppId, RoleName } from "../../types.js";
|
|
3
|
-
import { AgentInfoRequest, AgentInfoResponse, PeerMetaInfoRequest, PeerMetaInfoResponse, AppInfo, DumpNetworkMetricsRequest, DumpNetworkMetricsResponse,
|
|
3
|
+
import { AgentInfoRequest, AgentInfoResponse, PeerMetaInfoRequest, PeerMetaInfoResponse, AppInfo, DumpNetworkMetricsRequest, DumpNetworkMetricsResponse, DumpNetworkStatsResponse, MemproofMap } from "../admin/index.js";
|
|
4
4
|
import { WsClient } from "../client.js";
|
|
5
5
|
import { AbandonCountersigningSessionStateRequest, AppClient, AppEvents, AppWebsocketConnectionOptions, CallZomeRequest, CallZomeRequestSigned, CreateCloneCellRequest, DisableCloneCellRequest, EnableCloneCellRequest, GetCountersigningSessionStateRequest, GetCountersigningSessionStateResponse, PublishCountersigningSessionStateRequest, RoleNameCallZomeRequest, SignalCb } from "./types.js";
|
|
6
6
|
/**
|
|
@@ -67,7 +67,7 @@ export declare class AppWebsocket implements AppClient {
|
|
|
67
67
|
*
|
|
68
68
|
* @returns The conductor's {@link TransportStats}.
|
|
69
69
|
*/
|
|
70
|
-
dumpNetworkStats(timeout?: number): Promise<
|
|
70
|
+
dumpNetworkStats(timeout?: number): Promise<DumpNetworkStatsResponse>;
|
|
71
71
|
/**
|
|
72
72
|
* Request network metrics.
|
|
73
73
|
*
|
package/lib/api/client.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class WsClient extends Emittery {
|
|
|
23
23
|
private pendingRequests;
|
|
24
24
|
private index;
|
|
25
25
|
private authenticationToken;
|
|
26
|
+
private reconnectPromise;
|
|
26
27
|
constructor(socket: IsoWebSocket, url?: URL, options?: WsClientOptions);
|
|
27
28
|
/**
|
|
28
29
|
* Instance factory for creating WsClients.
|
|
@@ -53,8 +54,21 @@ export declare class WsClient extends Emittery {
|
|
|
53
54
|
/**
|
|
54
55
|
* Send requests to the connected websocket.
|
|
55
56
|
*
|
|
57
|
+
* If the underlying socket is closed when this method is called, the
|
|
58
|
+
* client transparently reconnects and re-authenticates using the cached
|
|
59
|
+
* token. Transient reconnect errors are surfaced as a `ConnectionError`
|
|
60
|
+
* and the cached token is retained, so a subsequent call can retry the
|
|
61
|
+
* reconnect.
|
|
62
|
+
*
|
|
63
|
+
* If the conductor rejects the cached token during the reconnect
|
|
64
|
+
* (signalled by an immediate close after the `authenticate` handshake),
|
|
65
|
+
* the cached token is cleared and the call rejects with an
|
|
66
|
+
* `InvalidTokenError`. The consumer must rebuild the `AppWebsocket`
|
|
67
|
+
* with a fresh token; further calls on this client will reject with
|
|
68
|
+
* `WebsocketClosedError`.
|
|
69
|
+
*
|
|
56
70
|
* @param request - The request to send over the websocket.
|
|
57
|
-
* @returns
|
|
71
|
+
* @returns The decoded response payload.
|
|
58
72
|
*/
|
|
59
73
|
request<Response>(request: unknown): Promise<Response>;
|
|
60
74
|
private exchange;
|
package/lib/api/client.js
CHANGED
|
@@ -19,6 +19,7 @@ export class WsClient extends Emittery {
|
|
|
19
19
|
pendingRequests;
|
|
20
20
|
index;
|
|
21
21
|
authenticationToken;
|
|
22
|
+
reconnectPromise;
|
|
22
23
|
constructor(socket, url, options) {
|
|
23
24
|
super();
|
|
24
25
|
this.registerMessageListener(socket);
|
|
@@ -100,8 +101,21 @@ export class WsClient extends Emittery {
|
|
|
100
101
|
/**
|
|
101
102
|
* Send requests to the connected websocket.
|
|
102
103
|
*
|
|
104
|
+
* If the underlying socket is closed when this method is called, the
|
|
105
|
+
* client transparently reconnects and re-authenticates using the cached
|
|
106
|
+
* token. Transient reconnect errors are surfaced as a `ConnectionError`
|
|
107
|
+
* and the cached token is retained, so a subsequent call can retry the
|
|
108
|
+
* reconnect.
|
|
109
|
+
*
|
|
110
|
+
* If the conductor rejects the cached token during the reconnect
|
|
111
|
+
* (signalled by an immediate close after the `authenticate` handshake),
|
|
112
|
+
* the cached token is cleared and the call rejects with an
|
|
113
|
+
* `InvalidTokenError`. The consumer must rebuild the `AppWebsocket`
|
|
114
|
+
* with a fresh token; further calls on this client will reject with
|
|
115
|
+
* `WebsocketClosedError`.
|
|
116
|
+
*
|
|
103
117
|
* @param request - The request to send over the websocket.
|
|
104
|
-
* @returns
|
|
118
|
+
* @returns The decoded response payload.
|
|
105
119
|
*/
|
|
106
120
|
async request(request) {
|
|
107
121
|
return this.exchange(request, this.sendMessage.bind(this));
|
|
@@ -114,7 +128,15 @@ export class WsClient extends Emittery {
|
|
|
114
128
|
return promise;
|
|
115
129
|
}
|
|
116
130
|
else if (this.url && this.authenticationToken) {
|
|
117
|
-
|
|
131
|
+
// Dedupe concurrent reconnect attempts. The first caller into this
|
|
132
|
+
// branch starts a single reconnect; further callers await the same
|
|
133
|
+
// promise so we never create multiple sockets in parallel.
|
|
134
|
+
if (!this.reconnectPromise) {
|
|
135
|
+
this.reconnectPromise = this.reconnectWebsocket(this.url, this.authenticationToken).finally(() => {
|
|
136
|
+
this.reconnectPromise = undefined;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
await this.reconnectPromise;
|
|
118
140
|
this.registerMessageListener(this.socket);
|
|
119
141
|
this.registerCloseListener(this.socket);
|
|
120
142
|
const promise = new Promise((resolve, reject) => sendHandler(request, resolve, reject));
|
|
@@ -204,19 +226,28 @@ export class WsClient extends Emittery {
|
|
|
204
226
|
async reconnectWebsocket(url, token) {
|
|
205
227
|
return new Promise((resolve, reject) => {
|
|
206
228
|
this.socket = new IsoWebSocket(url, this.options);
|
|
229
|
+
// Track whether the "open" event has fired. The invalidTokenCloseListener
|
|
230
|
+
// must only clear the token when the connection did open and the conductor
|
|
231
|
+
// then closed it quickly.
|
|
232
|
+
let openFired = false;
|
|
207
233
|
// This error event never occurs in tests. Could be removed?
|
|
208
234
|
this.socket.addEventListener("error", (errorEvent) => {
|
|
209
|
-
this.authenticationToken = undefined;
|
|
210
235
|
reject(new HolochainError("ConnectionError", `could not connect to Holochain Conductor API at ${url} - ${errorEvent.message}`));
|
|
211
236
|
}, { once: true });
|
|
212
237
|
const invalidTokenCloseListener = (closeEvent) => {
|
|
213
|
-
|
|
214
|
-
|
|
238
|
+
if (openFired) {
|
|
239
|
+
this.authenticationToken = undefined;
|
|
240
|
+
reject(new HolochainError("InvalidTokenError", `could not connect to ${this.url} due to an invalid app authentication token - close code ${closeEvent.code}`));
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
reject(new HolochainError("ConnectionError", `could not connect to Holochain Conductor API at ${url} - close code ${closeEvent.code}`));
|
|
244
|
+
}
|
|
215
245
|
};
|
|
216
246
|
this.socket.addEventListener("close", invalidTokenCloseListener, {
|
|
217
247
|
once: true,
|
|
218
248
|
});
|
|
219
249
|
this.socket.addEventListener("open", async () => {
|
|
250
|
+
openFired = true;
|
|
220
251
|
const encodedMsg = encode({
|
|
221
252
|
type: "authenticate",
|
|
222
253
|
data: encode({ token }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holochain/client",
|
|
3
|
-
"version": "0.21.0-dev.
|
|
3
|
+
"version": "0.21.0-dev.3",
|
|
4
4
|
"description": "A JavaScript client for the Holochain Conductor API",
|
|
5
5
|
"author": "Holochain Foundation <info@holochain.org> (https://holochain.org)",
|
|
6
6
|
"license": "CAL-1.0",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"homepage": "https://github.com/holochain/holochain-client-js#readme",
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=20.0.0
|
|
21
|
+
"node": ">=20.0.0"
|
|
22
22
|
},
|
|
23
23
|
"main": "lib/index.js",
|
|
24
24
|
"module": "lib/index.js",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"lint": "eslint --fix --ext .ts src test eslint.config.cjs",
|
|
35
35
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
36
|
-
"test:app-agent": "RUST_LOG=error RUST_BACKTRACE=1
|
|
37
|
-
"test:utils": "RUST_LOG=error RUST_BACKTRACE=1
|
|
38
|
-
"test": "RUST_LOG=error RUST_BACKTRACE=1
|
|
36
|
+
"test:app-agent": "RUST_LOG=error RUST_BACKTRACE=1 vitest run app-websocket",
|
|
37
|
+
"test:utils": "RUST_LOG=error RUST_BACKTRACE=1 vitest run utils",
|
|
38
|
+
"test": "RUST_LOG=error RUST_BACKTRACE=1 vitest run",
|
|
39
39
|
"build:lib": "rimraf ./lib && tsc -p tsconfig.build.json",
|
|
40
40
|
"build:docs": "api-extractor run --local && api-documenter markdown -i docs/temp -o docs",
|
|
41
41
|
"build": "npm run build:lib && npm run build:docs",
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"@types/js-yaml": "4.0.9",
|
|
61
61
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
62
62
|
"@types/lodash-es": "^4.17.12",
|
|
63
|
-
"@types/tape": "^5.8.1",
|
|
64
63
|
"@types/ws": "^8.18.1",
|
|
65
64
|
"@typescript-eslint/eslint-plugin": "^8.48.1",
|
|
66
65
|
"@typescript-eslint/parser": "^8.48.1",
|
|
@@ -68,12 +67,13 @@
|
|
|
68
67
|
"eslint-config-prettier": "^10.1.8",
|
|
69
68
|
"eslint-plugin-prettier": "^5.5.4",
|
|
70
69
|
"eslint-plugin-tsdoc": "^0.5.0",
|
|
70
|
+
"get-port": "^7.1.0",
|
|
71
71
|
"globals": "^16.5.0",
|
|
72
72
|
"js-yaml": "^4.1.1",
|
|
73
73
|
"prettier": "^3.7.3",
|
|
74
74
|
"rimraf": "^6.1.2",
|
|
75
|
-
"tape": "^5.9.0",
|
|
76
75
|
"tsx": "^4.21.0",
|
|
77
|
-
"typescript": "^5.9.3"
|
|
76
|
+
"typescript": "^5.9.3",
|
|
77
|
+
"vitest": "^4.0.18"
|
|
78
78
|
}
|
|
79
79
|
}
|