@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 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
- const signalCb = (signal: AppSignal) => {
29
- // implementation of signal handler
30
- resolve()
31
- }
32
-
33
- const TIMEOUT = 12000
34
- // default timeout is set to 12000
35
- const appWs = await AppWebsocket.connect(`ws://127.0.0.1:${appPort}`, 12000)
36
-
37
- const client = new AppAgentWebsocket(appWs, 'installed_app_id');
38
- client.on("signal", signalCb);
39
-
40
- // default timeout set here (30000) will overwrite the defaultTimeout(12000) set above
41
- await client.callZome({
42
- role_name: 'dnas_role_name', // role_name is unique per app, so you can unambiguously identify your dna with role_name in this client
43
- zome_name: "test_zome",
44
- fn_name: 'test_emitter_fn',
45
- payload: null,
46
- }, 30000)
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
- const signalCb = (signal: AppSignal) => {
52
- // impl...
53
- resolve()
54
- }
55
-
56
- const TIMEOUT = 12000
57
- // default timeout is set to 12000
58
- const client = await AppWebsocket.connect(`ws://127.0.0.1:${appPort}`, TIMEOUT, signalCb)
59
-
60
- // default timeout set here (30000) will overwrite the defaultTimeout(12000) set above
61
- await client.callZome({
62
- cell_id,
63
- zome_name: "test_zome",
64
- fn_name: 'test_emitter_fn',
65
- provenance: agentPubKey,
66
- payload: null,
67
- }, 30000)
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 our [forum](https://forum.holochain.org)
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 (!("provenance" in request)) {
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
- else {
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.
@@ -42,5 +42,5 @@ export declare class WsClient extends Emittery {
42
42
  /**
43
43
  * Close the websocket connection.
44
44
  */
45
- close(): Promise<void>;
45
+ close(code?: number): Promise<void>;
46
46
  }
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 readible content to the UI, the signal payload must also be deserialized.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holochain/client",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "description": "A JavaScript client for the Holochain Conductor API",
5
5
  "author": "Holochain Foundation <info@holochain.org> (http://holochain.org)",
6
6
  "license": "CAL-1.0",