@holochain/client 0.12.2 → 0.12.4
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 +90 -37
- package/lib/api/app-agent/websocket.js +7 -4
- package/lib/api/client.d.ts +1 -1
- package/lib/api/client.js +24 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,46 +25,99 @@ npm install --save-exact @holochain/client
|
|
|
25
25
|
|
|
26
26
|
### Use AppAgentWebsocket with implicit zome call signing
|
|
27
27
|
```typescript
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
28
|
+
import { AdminWebsocket, AppAgentWebsocket, CellType } from "@holochain/client";
|
|
29
|
+
|
|
30
|
+
const adminWs = await AdminWebsocket.connect("ws://127.0.0.1:65000");
|
|
31
|
+
const agent_key = await adminWs.generateAgentPubKey();
|
|
32
|
+
const role_name = "role";
|
|
33
|
+
const installed_app_id = "test-app";
|
|
34
|
+
const appInfo = await adminWs.installApp({
|
|
35
|
+
agent_key,
|
|
36
|
+
path: "path/to/happ/file",
|
|
37
|
+
installed_app_id,
|
|
38
|
+
membrane_proofs: {},
|
|
39
|
+
});
|
|
40
|
+
await adminWs.enableApp({ installed_app_id });
|
|
41
|
+
if (!(CellType.Provisioned in appInfo.cell_info[role_name][0])) {
|
|
42
|
+
process.exit();
|
|
43
|
+
}
|
|
44
|
+
const { cell_id } = appInfo.cell_info[role_name][0][CellType.Provisioned];
|
|
45
|
+
await adminWs.authorizeSigningCredentials(cell_id);
|
|
46
|
+
await adminWs.attachAppInterface({ port: 65001 });
|
|
47
|
+
const appAgentWs = await AppAgentWebsocket.connect(
|
|
48
|
+
"ws://127.0.0.1:65001",
|
|
49
|
+
installed_app_id
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
let signalCb;
|
|
53
|
+
const signalReceived = new Promise<void>((resolve) => {
|
|
54
|
+
signalCb = (signal) => {
|
|
55
|
+
console.log("signal received", signal);
|
|
56
|
+
// act on signal
|
|
57
|
+
resolve();
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
appAgentWs.on("signal", signalCb);
|
|
62
|
+
|
|
63
|
+
// trigger an emit_signal
|
|
64
|
+
await appAgentWs.callZome({
|
|
65
|
+
role_name,
|
|
66
|
+
zome_name: "zome",
|
|
67
|
+
fn_name: "emitter",
|
|
68
|
+
payload: null,
|
|
69
|
+
});
|
|
70
|
+
await signalReceived;
|
|
71
|
+
|
|
72
|
+
await appAgentWs.appWebsocket.client.close();
|
|
73
|
+
await adminWs.client.close();
|
|
47
74
|
```
|
|
48
75
|
|
|
49
76
|
### Use AppWebsocket with implicit zome call signing
|
|
50
77
|
```typescript
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
import { AdminWebsocket, AppWebsocket, CellType } from "@holochain/client";
|
|
79
|
+
|
|
80
|
+
const adminWs = await AdminWebsocket.connect("ws://127.0.0.1:65000");
|
|
81
|
+
const agent_key = await adminWs.generateAgentPubKey();
|
|
82
|
+
const installed_app_id = "test-app";
|
|
83
|
+
const appInfo = await adminWs.installApp({
|
|
84
|
+
agent_key,
|
|
85
|
+
path: "path/to/happ/file",
|
|
86
|
+
installed_app_id,
|
|
87
|
+
membrane_proofs: {},
|
|
88
|
+
});
|
|
89
|
+
await adminWs.enableApp({ installed_app_id });
|
|
90
|
+
if (!(CellType.Provisioned in appInfo.cell_info["role"][0])) {
|
|
91
|
+
process.exit();
|
|
92
|
+
}
|
|
93
|
+
const { cell_id } = appInfo.cell_info["role"][0][CellType.Provisioned];
|
|
94
|
+
await adminWs.authorizeSigningCredentials(cell_id);
|
|
95
|
+
await adminWs.attachAppInterface({ port: 65001 });
|
|
96
|
+
const appWs = await AppWebsocket.connect("ws://127.0.0.1:65001");
|
|
97
|
+
|
|
98
|
+
let signalCb;
|
|
99
|
+
const signalReceived = new Promise<void>((resolve) => {
|
|
100
|
+
signalCb = (signal) => {
|
|
101
|
+
console.log("signal received", signal);
|
|
102
|
+
// act on signal
|
|
103
|
+
resolve();
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
appWs.on("signal", signalCb);
|
|
108
|
+
|
|
109
|
+
// trigger an emit_signal
|
|
110
|
+
await appWs.callZome({
|
|
111
|
+
cell_id,
|
|
112
|
+
zome_name: "zome",
|
|
113
|
+
fn_name: "emitter",
|
|
114
|
+
provenance: agent_key,
|
|
115
|
+
payload: null,
|
|
116
|
+
});
|
|
117
|
+
await signalReceived;
|
|
118
|
+
|
|
119
|
+
await appWs.client.close();
|
|
120
|
+
await adminWs.client.close();
|
|
68
121
|
```
|
|
69
122
|
|
|
70
123
|
### Managing zome call signing credentials in a pure JavaScript browser application
|
|
@@ -119,7 +172,7 @@ nix-shell
|
|
|
119
172
|
|
|
120
173
|
Holochain is an open source project. We welcome all sorts of participation and are actively working on increasing surface area to accept it. Please see our [contribution guidelines](/CONTRIBUTING.md) for our general practices and protocols on participating in the community, as well as specific expectations around things like code formatting, testing practices, continuous integration, etc.
|
|
121
174
|
|
|
122
|
-
* Connect with us on
|
|
175
|
+
* Connect with us on [Discord](https://discord.gg/k55DS5dmPH)
|
|
123
176
|
|
|
124
177
|
## License
|
|
125
178
|
|
|
@@ -92,7 +92,12 @@ export class AppAgentWebsocket {
|
|
|
92
92
|
* @returns The zome call's response.
|
|
93
93
|
*/
|
|
94
94
|
async callZome(request, timeout) {
|
|
95
|
-
if (
|
|
95
|
+
if ("provenance" in request) {
|
|
96
|
+
if ("role_name" in request && request.role_name) {
|
|
97
|
+
throw new Error("Cannot find other agent's cells based on role name. Use cell id when providing a provenance.");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
96
101
|
request = {
|
|
97
102
|
...request,
|
|
98
103
|
provenance: this.myPubKey,
|
|
@@ -111,9 +116,7 @@ export class AppAgentWebsocket {
|
|
|
111
116
|
else if ("cell_id" in request && request.cell_id) {
|
|
112
117
|
return this.appWebsocket.callZome(request, timeout);
|
|
113
118
|
}
|
|
114
|
-
|
|
115
|
-
throw new Error("callZome requires a role_name or cell_id arg");
|
|
116
|
-
}
|
|
119
|
+
throw new Error("callZome requires a role_name or cell_id arg");
|
|
117
120
|
}
|
|
118
121
|
/**
|
|
119
122
|
* Clone an existing provisioned cell.
|
package/lib/api/client.d.ts
CHANGED
package/lib/api/client.js
CHANGED
|
@@ -48,7 +48,7 @@ export class WsClient extends Emittery {
|
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
const encodedAppSignal = deserializedSignal[SignalType.App];
|
|
51
|
-
// In order to return
|
|
51
|
+
// In order to return readable content to the UI, the signal payload must also be deserialized.
|
|
52
52
|
const payload = decode(encodedAppSignal.signal);
|
|
53
53
|
const signal = {
|
|
54
54
|
cell_id: encodedAppSignal.cell_id,
|
|
@@ -64,6 +64,16 @@ export class WsClient extends Emittery {
|
|
|
64
64
|
console.error(`Got unrecognized Websocket message type: ${message.type}`);
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
|
+
socket.on("close", (event) => {
|
|
68
|
+
const pendingRequestIds = Object.keys(this.pendingRequests).map((id) => parseInt(id));
|
|
69
|
+
if (pendingRequestIds.length) {
|
|
70
|
+
pendingRequestIds.forEach((id) => {
|
|
71
|
+
const error = new Error(`Websocket closed with pending requests. Close event: ${event}, request id: ${id}`);
|
|
72
|
+
this.pendingRequests[id].reject(error);
|
|
73
|
+
delete this.pendingRequests[id];
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
67
77
|
}
|
|
68
78
|
/**
|
|
69
79
|
* Instance factory for creating WsClients.
|
|
@@ -105,23 +115,23 @@ export class WsClient extends Emittery {
|
|
|
105
115
|
* @returns
|
|
106
116
|
*/
|
|
107
117
|
request(request) {
|
|
108
|
-
const id = this.index;
|
|
109
|
-
this.index += 1;
|
|
110
|
-
const encodedMsg = encode({
|
|
111
|
-
id,
|
|
112
|
-
type: "request",
|
|
113
|
-
data: encode(request),
|
|
114
|
-
});
|
|
115
|
-
const promise = new Promise((resolve, reject) => {
|
|
116
|
-
this.pendingRequests[id] = { resolve, reject };
|
|
117
|
-
});
|
|
118
118
|
if (this.socket.readyState === this.socket.OPEN) {
|
|
119
|
+
const id = this.index;
|
|
120
|
+
const encodedMsg = encode({
|
|
121
|
+
id,
|
|
122
|
+
type: "request",
|
|
123
|
+
data: encode(request),
|
|
124
|
+
});
|
|
125
|
+
const promise = new Promise((resolve, reject) => {
|
|
126
|
+
this.pendingRequests[id] = { resolve, reject };
|
|
127
|
+
});
|
|
119
128
|
this.socket.send(encodedMsg);
|
|
129
|
+
this.index += 1;
|
|
130
|
+
return promise;
|
|
120
131
|
}
|
|
121
132
|
else {
|
|
122
133
|
return Promise.reject(new Error("Socket is not open"));
|
|
123
134
|
}
|
|
124
|
-
return promise;
|
|
125
135
|
}
|
|
126
136
|
handleResponse(msg) {
|
|
127
137
|
const id = msg.id;
|
|
@@ -141,9 +151,9 @@ export class WsClient extends Emittery {
|
|
|
141
151
|
/**
|
|
142
152
|
* Close the websocket connection.
|
|
143
153
|
*/
|
|
144
|
-
close() {
|
|
154
|
+
close(code) {
|
|
145
155
|
const closedPromise = new Promise((resolve) => this.socket.on("close", resolve));
|
|
146
|
-
this.socket.close();
|
|
156
|
+
this.socket.close(code);
|
|
147
157
|
return closedPromise;
|
|
148
158
|
}
|
|
149
159
|
}
|
package/package.json
CHANGED