@tdxvolt/volt-client-grpc 0.14.134 → 0.15.1
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/index.cjs +159 -93
- package/package.json +1 -1
- package/src/grpc-utils.js +9 -9
- package/src/rpc-invocation.js +25 -21
- package/src/utils.js +43 -2
- package/src/volt-client-internal.js +23 -19
- package/src/volt-client.js +34 -19
- package/src/volt-connection.js +7 -5
- package/src/volt-credential.js +17 -19
package/package.json
CHANGED
package/src/grpc-utils.js
CHANGED
|
@@ -16,7 +16,7 @@ export function createClient(
|
|
|
16
16
|
credentials,
|
|
17
17
|
noSerialise,
|
|
18
18
|
voltId,
|
|
19
|
-
serviceId
|
|
19
|
+
serviceId
|
|
20
20
|
) {
|
|
21
21
|
let grpcCredentials;
|
|
22
22
|
if (credentials) {
|
|
@@ -30,7 +30,7 @@ export function createClient(
|
|
|
30
30
|
grpcCredentials = grpc.credentials.createSsl(
|
|
31
31
|
tlsOptions.ca,
|
|
32
32
|
tlsOptions.key,
|
|
33
|
-
tlsOptions.cert
|
|
33
|
+
tlsOptions.cert
|
|
34
34
|
);
|
|
35
35
|
} else {
|
|
36
36
|
// Cache has no private key, this implies we are connecting without supplying a client certificate.
|
|
@@ -92,7 +92,7 @@ const grpcWrap = (api) => {
|
|
|
92
92
|
// Support class instances and PoJos
|
|
93
93
|
const isClass = api.constructor !== Object;
|
|
94
94
|
const iterate = Object.getOwnPropertyNames(
|
|
95
|
-
isClass ? api.constructor.prototype : api
|
|
95
|
+
isClass ? api.constructor.prototype : api
|
|
96
96
|
);
|
|
97
97
|
|
|
98
98
|
// Wrap each method on the api.
|
|
@@ -106,7 +106,7 @@ const grpcWrap = (api) => {
|
|
|
106
106
|
// Enforce promise results.
|
|
107
107
|
if (!(resultPromise?.then && resultPromise?.catch)) {
|
|
108
108
|
throw new Error(
|
|
109
|
-
`implementation methods must return a Promise [${name}]
|
|
109
|
+
`implementation methods must return a Promise [${name}]`
|
|
110
110
|
);
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -143,7 +143,7 @@ class GrpcServer {
|
|
|
143
143
|
"grpc.http2.max_pings_without_data": 0,
|
|
144
144
|
"grpc.keepalive_permit_without_calls": 1,
|
|
145
145
|
"grpc.http2.min_ping_interval_without_data_ms": 250,
|
|
146
|
-
"grpc.http2.max_ping_strikes": 0
|
|
146
|
+
"grpc.http2.max_ping_strikes": 0
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
if (tlsOptions) {
|
|
@@ -153,7 +153,7 @@ class GrpcServer {
|
|
|
153
153
|
caList.push(tlsOption.ca);
|
|
154
154
|
certChains.push({
|
|
155
155
|
private_key: tlsOption.key,
|
|
156
|
-
cert_chain: tlsOption.cert
|
|
156
|
+
cert_chain: tlsOption.cert
|
|
157
157
|
});
|
|
158
158
|
});
|
|
159
159
|
|
|
@@ -164,7 +164,7 @@ class GrpcServer {
|
|
|
164
164
|
// The certificate chain(s) we present to the client.
|
|
165
165
|
certChains,
|
|
166
166
|
// Flag indicating if we insist on a client certificate.
|
|
167
|
-
requireClientCert
|
|
167
|
+
requireClientCert
|
|
168
168
|
);
|
|
169
169
|
} else {
|
|
170
170
|
this._credentials = grpc.ServerCredentials.createInsecure();
|
|
@@ -216,7 +216,7 @@ export function createServer(
|
|
|
216
216
|
serviceDescriptors,
|
|
217
217
|
routes,
|
|
218
218
|
cryptoCache,
|
|
219
|
-
requireClientCert
|
|
219
|
+
requireClientCert
|
|
220
220
|
) {
|
|
221
221
|
let tlsOptions;
|
|
222
222
|
if (cryptoCache) {
|
|
@@ -227,7 +227,7 @@ export function createServer(
|
|
|
227
227
|
serviceDescriptors,
|
|
228
228
|
routes,
|
|
229
229
|
tlsOptions,
|
|
230
|
-
requireClientCert
|
|
230
|
+
requireClientCert
|
|
231
231
|
};
|
|
232
232
|
return new GrpcServer(serverArgs);
|
|
233
233
|
}
|
package/src/rpc-invocation.js
CHANGED
|
@@ -39,12 +39,12 @@ class RpcInvocation extends EventEmitter {
|
|
|
39
39
|
deserialisedPayload = this.#payload;
|
|
40
40
|
} else if (this.#methodDescriptor) {
|
|
41
41
|
deserialisedPayload = this.#methodDescriptor.requestDeserialize(
|
|
42
|
-
this.#payload
|
|
42
|
+
this.#payload
|
|
43
43
|
);
|
|
44
44
|
} else {
|
|
45
45
|
log("unexpected: no method descriptor");
|
|
46
46
|
throw new Error(
|
|
47
|
-
"no method descriptor - set this before accessing payload"
|
|
47
|
+
"no method descriptor - set this before accessing payload"
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -68,11 +68,11 @@ class RpcInvocation extends EventEmitter {
|
|
|
68
68
|
// Decrypt the shared key and iv using the private key.
|
|
69
69
|
this.#encryptKey = VoltCredential.rsaDecrypt(
|
|
70
70
|
this.#voltClient.credential.cache.key,
|
|
71
|
-
this.#token.sk
|
|
71
|
+
this.#token.sk
|
|
72
72
|
);
|
|
73
73
|
this.#encryptIV = VoltCredential.rsaDecrypt(
|
|
74
74
|
this.#voltClient.credential.cache.key,
|
|
75
|
-
this.#token.iv
|
|
75
|
+
this.#token.iv
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -103,7 +103,7 @@ class RpcInvocation extends EventEmitter {
|
|
|
103
103
|
decryptedPayload = VoltCredential.aesDecrypt(
|
|
104
104
|
invoke_request.payload,
|
|
105
105
|
this.#encryptKey,
|
|
106
|
-
this.#encryptIV
|
|
106
|
+
this.#encryptIV
|
|
107
107
|
);
|
|
108
108
|
} else {
|
|
109
109
|
// No encryption => just use the payload.
|
|
@@ -124,9 +124,13 @@ class RpcInvocation extends EventEmitter {
|
|
|
124
124
|
this.#payload = wrappedPayload.method_payload.payload;
|
|
125
125
|
this.emit("payload", this);
|
|
126
126
|
} else if (wrappedPayload.method_end) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
this.#payload = wrappedPayload.method_end;
|
|
128
|
+
if (wrappedPayload.method_end.error) {
|
|
129
|
+
// The client has sent an error.
|
|
130
|
+
this.emit("error", this);
|
|
131
|
+
} else {
|
|
132
|
+
this.emit("end", this);
|
|
133
|
+
}
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
resolve();
|
|
@@ -140,7 +144,7 @@ class RpcInvocation extends EventEmitter {
|
|
|
140
144
|
decryptedPayload = VoltCredential.aesDecrypt(
|
|
141
145
|
Buffer.from(invoke_request.json_payload, "base64"),
|
|
142
146
|
this.#encryptKey,
|
|
143
|
-
this.#encryptIV
|
|
147
|
+
this.#encryptIV
|
|
144
148
|
);
|
|
145
149
|
} else {
|
|
146
150
|
// No encryption => just use the payload.
|
|
@@ -153,12 +157,12 @@ class RpcInvocation extends EventEmitter {
|
|
|
153
157
|
if (wrappedPayload.method_invoke) {
|
|
154
158
|
this.#methodName = wrappedPayload.method_invoke.method_name;
|
|
155
159
|
this.#payload = JSON.parse(
|
|
156
|
-
wrappedPayload.method_invoke.json_request
|
|
160
|
+
wrappedPayload.method_invoke.json_request
|
|
157
161
|
);
|
|
158
162
|
this.emit("payload", this);
|
|
159
163
|
} else if (wrappedPayload.method_payload) {
|
|
160
164
|
this.#payload = JSON.parse(
|
|
161
|
-
wrappedPayload.method_payload.json_payload
|
|
165
|
+
wrappedPayload.method_payload.json_payload
|
|
162
166
|
);
|
|
163
167
|
this.emit("payload", this);
|
|
164
168
|
} else if (wrappedPayload.method_end) {
|
|
@@ -187,7 +191,7 @@ class RpcInvocation extends EventEmitter {
|
|
|
187
191
|
let responsePayload;
|
|
188
192
|
if (this.#isJSON) {
|
|
189
193
|
responsePayload = JSON.stringify({
|
|
190
|
-
method_payload: { json_payload: JSON.stringify(response) }
|
|
194
|
+
method_payload: { json_payload: JSON.stringify(response) }
|
|
191
195
|
});
|
|
192
196
|
} else {
|
|
193
197
|
// We need to serialise the response, and then wrap it in a RemoteRequest.
|
|
@@ -195,7 +199,7 @@ class RpcInvocation extends EventEmitter {
|
|
|
195
199
|
this.#methodDescriptor.responseSerialize(response);
|
|
196
200
|
const tunnelMethod = this.#voltClient.getVoltAPIClient().Tunnel;
|
|
197
201
|
responsePayload = tunnelMethod.requestSerialize({
|
|
198
|
-
method_payload: { payload: serialisedResponse }
|
|
202
|
+
method_payload: { payload: serialisedResponse }
|
|
199
203
|
});
|
|
200
204
|
}
|
|
201
205
|
|
|
@@ -204,12 +208,12 @@ class RpcInvocation extends EventEmitter {
|
|
|
204
208
|
responsePayload = VoltCredential.aesEncrypt(
|
|
205
209
|
responsePayload,
|
|
206
210
|
this.#encryptKey,
|
|
207
|
-
this.#encryptIV
|
|
211
|
+
this.#encryptIV
|
|
208
212
|
);
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
const invokeResponse = {
|
|
212
|
-
invoke_id: this.#invokeId
|
|
216
|
+
invoke_id: this.#invokeId
|
|
213
217
|
};
|
|
214
218
|
|
|
215
219
|
if (this.#isJSON) {
|
|
@@ -220,7 +224,7 @@ class RpcInvocation extends EventEmitter {
|
|
|
220
224
|
}
|
|
221
225
|
|
|
222
226
|
this.#voltConnection.send({
|
|
223
|
-
invoke_response: invokeResponse
|
|
227
|
+
invoke_response: invokeResponse
|
|
224
228
|
});
|
|
225
229
|
}
|
|
226
230
|
|
|
@@ -230,11 +234,11 @@ class RpcInvocation extends EventEmitter {
|
|
|
230
234
|
let endPayload;
|
|
231
235
|
if (errorMessage) {
|
|
232
236
|
endPayload = {
|
|
233
|
-
method_end: { error: errorMessage, ended: true }
|
|
237
|
+
method_end: { error: errorMessage, ended: true }
|
|
234
238
|
};
|
|
235
239
|
} else {
|
|
236
240
|
endPayload = {
|
|
237
|
-
method_end: { ended: true }
|
|
241
|
+
method_end: { ended: true }
|
|
238
242
|
};
|
|
239
243
|
}
|
|
240
244
|
|
|
@@ -249,13 +253,13 @@ class RpcInvocation extends EventEmitter {
|
|
|
249
253
|
endPayload = VoltCredential.aesEncrypt(
|
|
250
254
|
endPayload,
|
|
251
255
|
this.#encryptKey,
|
|
252
|
-
this.#encryptIV
|
|
256
|
+
this.#encryptIV
|
|
253
257
|
);
|
|
254
258
|
}
|
|
255
259
|
|
|
256
260
|
const invokeResponse = {
|
|
257
261
|
invoke_id: this.#invokeId,
|
|
258
|
-
server_end: true
|
|
262
|
+
server_end: true
|
|
259
263
|
};
|
|
260
264
|
|
|
261
265
|
if (this.#isJSON) {
|
|
@@ -265,7 +269,7 @@ class RpcInvocation extends EventEmitter {
|
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
this.#voltConnection.send({
|
|
268
|
-
invoke_response: invokeResponse
|
|
272
|
+
invoke_response: invokeResponse
|
|
269
273
|
});
|
|
270
274
|
}
|
|
271
275
|
}
|
package/src/utils.js
CHANGED
|
@@ -11,7 +11,7 @@ export const createSecureContextOptions = (cryptoOptions) => {
|
|
|
11
11
|
const tlsOptions = {
|
|
12
12
|
cert: Buffer.from(cryptoOptions.cert),
|
|
13
13
|
ca: Buffer.from(cryptoOptions.ca),
|
|
14
|
-
key: Buffer.from(cryptoOptions.key)
|
|
14
|
+
key: Buffer.from(cryptoOptions.key)
|
|
15
15
|
};
|
|
16
16
|
return tlsOptions;
|
|
17
17
|
};
|
|
@@ -27,7 +27,7 @@ export const getServiceAddress = (mdnsService) => {
|
|
|
27
27
|
const ipv4 = _.find(mdnsService.addresses, (addy) => ip.isV4Format(addy));
|
|
28
28
|
const serviceDetails = {
|
|
29
29
|
host: ipv4,
|
|
30
|
-
port: mdnsService.port
|
|
30
|
+
port: mdnsService.port
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
address = `${serviceDetails.host}:${serviceDetails.port}`;
|
|
@@ -103,3 +103,44 @@ export const getDIDResolutionURL = (didIn) => {
|
|
|
103
103
|
|
|
104
104
|
return `https://${hostName}/api/identity/${didGUID}`;
|
|
105
105
|
};
|
|
106
|
+
|
|
107
|
+
const forgePrivateKeyToPem = (decryptedKey) => {
|
|
108
|
+
// Convert a Forge private key to an ASN.1 RSAPrivateKey
|
|
109
|
+
const asnPrivateKey = pki.privateKeyToAsn1(decryptedKey);
|
|
110
|
+
|
|
111
|
+
// Wrap an RSAPrivateKey ASN.1 object in a PKCS#8 ASN.1 PrivateKeyInfo
|
|
112
|
+
const privateKeyInfo = pki.wrapRsaPrivateKey(asnPrivateKey);
|
|
113
|
+
|
|
114
|
+
// Convert a PKCS#8 ASN.1 PrivateKeyInfo to PEM
|
|
115
|
+
return pki.privateKeyInfoToPem(privateKeyInfo);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const createRSAKey = (passphrase = "") => {
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
pki.rsa.generateKeyPair({ bits: 2048, workers: -1 }, (err, keypair) => {
|
|
121
|
+
if (err) {
|
|
122
|
+
reject(err);
|
|
123
|
+
} else {
|
|
124
|
+
let pem;
|
|
125
|
+
if (passphrase) {
|
|
126
|
+
pem = pki.encryptRsaPrivateKey(keypair.privateKey, passphrase);
|
|
127
|
+
} else {
|
|
128
|
+
pem = forgePrivateKeyToPem(keypair.privateKey);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
resolve({ keypair, pem });
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const sha256Base64 = (msg) => {
|
|
138
|
+
const md = forge.md.sha256.create();
|
|
139
|
+
md.update(msg);
|
|
140
|
+
return forge.util.encode64(md.digest().bytes());
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const decryptPrivateKey = (pem, passphrase) => {
|
|
144
|
+
const decryptedKey = pki.decryptRsaPrivateKey(pem, passphrase);
|
|
145
|
+
return forgePrivateKeyToPem(decryptedKey);
|
|
146
|
+
};
|
|
@@ -9,7 +9,7 @@ import { join } from "path";
|
|
|
9
9
|
import {
|
|
10
10
|
createServiceProtobufFiles,
|
|
11
11
|
getServiceDescriptors,
|
|
12
|
-
getServiceDescriptorsFromPath
|
|
12
|
+
getServiceDescriptorsFromPath
|
|
13
13
|
} from "./proto-utils.js";
|
|
14
14
|
import { createClient as createGrpcClient } from "./grpc-utils.js";
|
|
15
15
|
import * as voltUtils from "./utils.js";
|
|
@@ -28,7 +28,7 @@ const voltServices = [
|
|
|
28
28
|
constants.serviceType.sqliteServerAPI,
|
|
29
29
|
constants.serviceType.ssiAPI,
|
|
30
30
|
constants.serviceType.relayAPI,
|
|
31
|
-
constants.serviceType.wireAPI
|
|
31
|
+
constants.serviceType.wireAPI
|
|
32
32
|
];
|
|
33
33
|
|
|
34
34
|
function issueBind(bindRequest, ttl) {
|
|
@@ -98,13 +98,13 @@ export async function bindInternal() {
|
|
|
98
98
|
log("attempting to retrieve Relay information from %s", relayURL);
|
|
99
99
|
this._voltConfig.relay = await fetchVoltConfig.call(
|
|
100
100
|
this,
|
|
101
|
-
`${relayURL}/discovery
|
|
101
|
+
`${relayURL}/discovery`
|
|
102
102
|
);
|
|
103
103
|
if (this._voltConfig.relay.ca_pem) {
|
|
104
104
|
log(
|
|
105
105
|
"Auto-fetched Relay CA %s, remote address %s",
|
|
106
106
|
this._voltConfig.relay.ca_pem,
|
|
107
|
-
this._voltConfig.relay.address
|
|
107
|
+
this._voltConfig.relay.address
|
|
108
108
|
);
|
|
109
109
|
} else {
|
|
110
110
|
throw new Error("Unable to fetch Relay CA - cannot securely connect.");
|
|
@@ -117,7 +117,7 @@ export async function bindInternal() {
|
|
|
117
117
|
|
|
118
118
|
if (!this._credential.cache.ca) {
|
|
119
119
|
throw new Error(
|
|
120
|
-
"No certificate authority found in configuration for target Volt - check configuration"
|
|
120
|
+
"No certificate authority found in configuration for target Volt - check configuration"
|
|
121
121
|
);
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -137,30 +137,30 @@ export async function bindInternal() {
|
|
|
137
137
|
binding_name: this._config.client_name,
|
|
138
138
|
public_key: publicKeyPem,
|
|
139
139
|
host: this._credential.cache.bindIp,
|
|
140
|
-
x509_credential: []
|
|
140
|
+
x509_credential: []
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
if (this._credential.cache.cert) {
|
|
144
144
|
bindRequest.x509_credential = [
|
|
145
|
-
this._credential.cache.cert + this._credential.cache.ca
|
|
145
|
+
this._credential.cache.cert + this._credential.cache.ca
|
|
146
146
|
];
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
if (this._voltConfig.challenge_code) {
|
|
150
150
|
bindRequest.challenge = voltUtils.signBase64(
|
|
151
151
|
keyPair.privateKey,
|
|
152
|
-
this._voltConfig.challenge_code
|
|
152
|
+
this._voltConfig.challenge_code
|
|
153
153
|
);
|
|
154
154
|
} else {
|
|
155
155
|
log(
|
|
156
|
-
"****no Volt challenge code available**** => not sending challenge signature"
|
|
156
|
+
"****no Volt challenge code available**** => not sending challenge signature"
|
|
157
157
|
);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
// For remote connections, add our cloud-issued certificate as an additional credential.
|
|
161
161
|
if (this._voltConfig?.relay?.ca_pem && this._credential.cache.cloud_cert) {
|
|
162
162
|
bindRequest.x509_credential = bindRequest.x509_credential.concat(
|
|
163
|
-
this._credential.cache.cloud_cert + this._voltConfig.relay.ca_pem
|
|
163
|
+
this._credential.cache.cloud_cert + this._voltConfig.relay.ca_pem
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -180,7 +180,7 @@ export async function bindInternal() {
|
|
|
180
180
|
decision = await issueBind.call(
|
|
181
181
|
this,
|
|
182
182
|
bindRequest,
|
|
183
|
-
this._voltConfig.bindRequestTTL
|
|
183
|
+
this._voltConfig.bindRequestTTL
|
|
184
184
|
);
|
|
185
185
|
log("binding decision: %s", decision);
|
|
186
186
|
} while (
|
|
@@ -241,6 +241,10 @@ export function connectInternal(helloPayload) {
|
|
|
241
241
|
this.emit("evt", evt);
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
this._voltConnection.on("ping", (ping) => {
|
|
245
|
+
this.emit("ping", ping);
|
|
246
|
+
});
|
|
247
|
+
|
|
244
248
|
this._voltConnection.on("invoke_request", (invoke_request) => {
|
|
245
249
|
const invokeId = invoke_request.invoke_id;
|
|
246
250
|
if (this._activeRPC[invokeId]) {
|
|
@@ -291,7 +295,7 @@ export function getVoltAPIClientInternal() {
|
|
|
291
295
|
this._credential,
|
|
292
296
|
this.isRemote && !this.isVoltRelay,
|
|
293
297
|
this._voltConfig?.relay?.cloud ? this._voltConfig.id : "",
|
|
294
|
-
this._voltConfig?.relay?.cloud ? this._voltConfig.id : ""
|
|
298
|
+
this._voltConfig?.relay?.cloud ? this._voltConfig.id : ""
|
|
295
299
|
);
|
|
296
300
|
}
|
|
297
301
|
|
|
@@ -316,7 +320,7 @@ export function getAPIClientInternal(service) {
|
|
|
316
320
|
const packageDescriptors = getServiceDescriptorsFromPath(
|
|
317
321
|
this._grpc,
|
|
318
322
|
fullProtoPath,
|
|
319
|
-
api
|
|
323
|
+
api
|
|
320
324
|
);
|
|
321
325
|
serviceDescriptors = { ...serviceDescriptors, ...packageDescriptors };
|
|
322
326
|
}
|
|
@@ -328,7 +332,7 @@ export function getAPIClientInternal(service) {
|
|
|
328
332
|
this._credential,
|
|
329
333
|
this.isRemote && !this.isVoltRelay,
|
|
330
334
|
this._voltConfig?.relay?.cloud ? this._voltConfig.id : "",
|
|
331
|
-
this._voltConfig?.relay?.cloud ? this._voltConfig.id : ""
|
|
335
|
+
this._voltConfig?.relay?.cloud ? this._voltConfig.id : ""
|
|
332
336
|
);
|
|
333
337
|
}
|
|
334
338
|
|
|
@@ -410,13 +414,13 @@ export async function fetchVoltConfig(discovery_url) {
|
|
|
410
414
|
"ca_pem",
|
|
411
415
|
"challenge_code",
|
|
412
416
|
"cloud",
|
|
413
|
-
"relay"
|
|
417
|
+
"relay"
|
|
414
418
|
);
|
|
415
419
|
|
|
416
420
|
return voltConfig;
|
|
417
421
|
} catch (err) {
|
|
418
422
|
throw new Error(
|
|
419
|
-
`Failure loading config from ${discovery_url}: ${err.message}
|
|
423
|
+
`Failure loading config from ${discovery_url}: ${err.message}`
|
|
420
424
|
);
|
|
421
425
|
}
|
|
422
426
|
}
|
|
@@ -432,13 +436,13 @@ export async function fetchVoltConfigFromDID(volt_did) {
|
|
|
432
436
|
const didDocument = await getJSON(didResolution);
|
|
433
437
|
const voltConfigServices = findDIDDocumentService(
|
|
434
438
|
didDocument,
|
|
435
|
-
constants.didServiceType.voltConfig
|
|
439
|
+
constants.didServiceType.voltConfig
|
|
436
440
|
);
|
|
437
441
|
if (voltConfigServices.length !== 1) {
|
|
438
442
|
log(
|
|
439
443
|
"Unexpected number of Volt configuration endpoints found in DID document for %s, services found: %d",
|
|
440
444
|
volt_did,
|
|
441
|
-
voltConfigServices.length
|
|
445
|
+
voltConfigServices.length
|
|
442
446
|
);
|
|
443
447
|
}
|
|
444
448
|
|
|
@@ -446,7 +450,7 @@ export async function fetchVoltConfigFromDID(volt_did) {
|
|
|
446
450
|
return await fetchVoltConfig.call(this, serviceEndpoint);
|
|
447
451
|
} catch (err) {
|
|
448
452
|
throw new Error(
|
|
449
|
-
`Failure fetching Volt config from DID document ${volt_did}: ${err.message}
|
|
453
|
+
`Failure fetching Volt config from DID document ${volt_did}: ${err.message}`
|
|
450
454
|
);
|
|
451
455
|
}
|
|
452
456
|
}
|
package/src/volt-client.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
fetchVoltConfigFromDID,
|
|
12
12
|
getVoltAPIClientInternal,
|
|
13
13
|
unaryCallInternal,
|
|
14
|
-
streamingCallInternal
|
|
14
|
+
streamingCallInternal
|
|
15
15
|
} from "./volt-client-internal.js";
|
|
16
16
|
import fs from "fs";
|
|
17
17
|
import GRPCCall from "./grpc-call.js";
|
|
@@ -64,7 +64,7 @@ export class VoltClient extends EventEmitter {
|
|
|
64
64
|
try {
|
|
65
65
|
if (!config) {
|
|
66
66
|
throw new Error(
|
|
67
|
-
"configPath argument is required to be a non-empty string"
|
|
67
|
+
"configPath argument is required to be a non-empty string"
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -75,13 +75,13 @@ export class VoltClient extends EventEmitter {
|
|
|
75
75
|
log("Attempt to load config from file %s", configPath);
|
|
76
76
|
try {
|
|
77
77
|
const configContents = await readFile(
|
|
78
|
-
new URL(configPath, import.meta.url)
|
|
78
|
+
new URL(configPath, import.meta.url)
|
|
79
79
|
);
|
|
80
80
|
configJSON = JSON.parse(configContents);
|
|
81
81
|
} catch (err) {
|
|
82
82
|
log("failure loading config file %s [%s]", configPath, err.message);
|
|
83
83
|
throw new Error(
|
|
84
|
-
`failed to load configuration - check JSON format in ${configPath}
|
|
84
|
+
`failed to load configuration - check JSON format in ${configPath}`
|
|
85
85
|
);
|
|
86
86
|
}
|
|
87
87
|
} else if (typeof config === "object") {
|
|
@@ -122,14 +122,14 @@ export class VoltClient extends EventEmitter {
|
|
|
122
122
|
const didConfig = await fetchVoltConfigFromDID.call(this, voltDID);
|
|
123
123
|
this._config = { ...this._config, volt: didConfig };
|
|
124
124
|
log("resolved config from DID: %s", JSON.stringify(didConfig, null, 2));
|
|
125
|
-
} else if (voltHttpAddress) {
|
|
125
|
+
} else if (voltHttpAddress && !this._config?.volt?.id) {
|
|
126
126
|
const discoConfig = await fetchVoltConfig.call(
|
|
127
127
|
this,
|
|
128
|
-
`${voltHttpAddress}/discovery
|
|
128
|
+
`${voltHttpAddress}/discovery`
|
|
129
129
|
);
|
|
130
130
|
this._config = {
|
|
131
131
|
...this._config,
|
|
132
|
-
volt: { ...this._config.volt, ...discoConfig }
|
|
132
|
+
volt: { ...this._config.volt, ...discoConfig }
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -173,7 +173,7 @@ export class VoltClient extends EventEmitter {
|
|
|
173
173
|
if (bindErr.message === "invalid arguments") {
|
|
174
174
|
// This is usually the result of a missing challenge signature or credential.
|
|
175
175
|
log(
|
|
176
|
-
"failure binding to Volt - did you supply a challenge code or verified credential?"
|
|
176
|
+
"failure binding to Volt - did you supply a challenge code or verified credential?"
|
|
177
177
|
);
|
|
178
178
|
throw bindErr;
|
|
179
179
|
}
|
|
@@ -236,7 +236,7 @@ export class VoltClient extends EventEmitter {
|
|
|
236
236
|
if (this.isRemote) {
|
|
237
237
|
if (!this._voltConfig?.relay?.address) {
|
|
238
238
|
throw new Error(
|
|
239
|
-
"Remote connection enabled but no Relay address - have you called start()?"
|
|
239
|
+
"Remote connection enabled but no Relay address - have you called start()?"
|
|
240
240
|
);
|
|
241
241
|
}
|
|
242
242
|
|
|
@@ -248,14 +248,14 @@ export class VoltClient extends EventEmitter {
|
|
|
248
248
|
this._credential,
|
|
249
249
|
false,
|
|
250
250
|
service.volt_id,
|
|
251
|
-
service.id
|
|
251
|
+
service.id
|
|
252
252
|
);
|
|
253
253
|
} else {
|
|
254
254
|
return createGrpcClient(
|
|
255
255
|
this._grpc,
|
|
256
256
|
serviceDescriptors,
|
|
257
257
|
service.service_description.address,
|
|
258
|
-
this._credential
|
|
258
|
+
this._credential
|
|
259
259
|
);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
@@ -293,7 +293,7 @@ export class VoltClient extends EventEmitter {
|
|
|
293
293
|
"METHOD_TYPE_BIDI",
|
|
294
294
|
method,
|
|
295
295
|
request,
|
|
296
|
-
service
|
|
296
|
+
service
|
|
297
297
|
);
|
|
298
298
|
}
|
|
299
299
|
|
|
@@ -303,7 +303,7 @@ export class VoltClient extends EventEmitter {
|
|
|
303
303
|
"METHOD_TYPE_CLIENT_STREAM",
|
|
304
304
|
method,
|
|
305
305
|
request,
|
|
306
|
-
service
|
|
306
|
+
service
|
|
307
307
|
);
|
|
308
308
|
}
|
|
309
309
|
|
|
@@ -313,7 +313,7 @@ export class VoltClient extends EventEmitter {
|
|
|
313
313
|
"METHOD_TYPE_SERVER_STREAM",
|
|
314
314
|
method,
|
|
315
315
|
request,
|
|
316
|
-
service
|
|
316
|
+
service
|
|
317
317
|
);
|
|
318
318
|
}
|
|
319
319
|
|
|
@@ -324,12 +324,12 @@ export class VoltClient extends EventEmitter {
|
|
|
324
324
|
*/
|
|
325
325
|
async RequestAccessBlocking(
|
|
326
326
|
targetResourceId,
|
|
327
|
-
accessType = "VOLT_ACCESS_READ"
|
|
327
|
+
accessType = "VOLT_ACCESS_READ"
|
|
328
328
|
) {
|
|
329
329
|
try {
|
|
330
330
|
const accessRequest = {
|
|
331
331
|
access: accessType,
|
|
332
|
-
resource_id: targetResourceId
|
|
332
|
+
resource_id: targetResourceId
|
|
333
333
|
};
|
|
334
334
|
|
|
335
335
|
// This will block while the request is pending.
|
|
@@ -498,11 +498,19 @@ export class VoltClient extends EventEmitter {
|
|
|
498
498
|
const downloadCall = new GRPCCall(
|
|
499
499
|
this,
|
|
500
500
|
"DownloadFile",
|
|
501
|
-
"METHOD_TYPE_SERVER_STREAM"
|
|
501
|
+
"METHOD_TYPE_SERVER_STREAM"
|
|
502
502
|
);
|
|
503
503
|
return downloadCall.start(grpcClient, request);
|
|
504
504
|
}
|
|
505
505
|
|
|
506
|
+
GetFileContent(request) {
|
|
507
|
+
return unaryCallInternal.call(this, "GetFileContent", request);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
SetFileContent(request) {
|
|
511
|
+
return unaryCallInternal.call(this, "SetFileContent", request);
|
|
512
|
+
}
|
|
513
|
+
|
|
506
514
|
UploadFile(request) {
|
|
507
515
|
const grpcClient = this.getVoltAPIClient();
|
|
508
516
|
|
|
@@ -524,7 +532,7 @@ export class VoltClient extends EventEmitter {
|
|
|
524
532
|
const call = new GRPCCall(
|
|
525
533
|
this,
|
|
526
534
|
"DownloadFile",
|
|
527
|
-
"METHOD_TYPE_SERVER_STREAM"
|
|
535
|
+
"METHOD_TYPE_SERVER_STREAM"
|
|
528
536
|
);
|
|
529
537
|
|
|
530
538
|
call.on("data", (response) => {
|
|
@@ -561,6 +569,13 @@ export class VoltClient extends EventEmitter {
|
|
|
561
569
|
});
|
|
562
570
|
}
|
|
563
571
|
|
|
572
|
+
/**
|
|
573
|
+
* SqliteServerAPI
|
|
574
|
+
*/
|
|
575
|
+
CreateDatabase(request) {
|
|
576
|
+
return unaryCallInternal.call(this, "CreateDatabase", request);
|
|
577
|
+
}
|
|
578
|
+
|
|
564
579
|
/**
|
|
565
580
|
* SqliteDatabaseAPI
|
|
566
581
|
*/
|
|
@@ -651,7 +666,7 @@ export class VoltClient extends EventEmitter {
|
|
|
651
666
|
const subscribeCall = new GRPCCall(
|
|
652
667
|
this,
|
|
653
668
|
"SubscribeWire",
|
|
654
|
-
"METHOD_TYPE_BIDI"
|
|
669
|
+
"METHOD_TYPE_BIDI"
|
|
655
670
|
);
|
|
656
671
|
return subscribeCall.start(grpcClient, request);
|
|
657
672
|
}
|
package/src/volt-connection.js
CHANGED
|
@@ -28,7 +28,7 @@ function _cleanUp(immediateReconnect) {
|
|
|
28
28
|
this._reconnectTimer = 0;
|
|
29
29
|
_doConnect.call(this, this._helloPayload);
|
|
30
30
|
},
|
|
31
|
-
immediateReconnect ? 0 : this._reconnectInterval
|
|
31
|
+
immediateReconnect ? 0 : this._reconnectInterval
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -49,10 +49,10 @@ function _doConnect(connectHello) {
|
|
|
49
49
|
const grpcClient = this._voltClient.getVoltAPIClient();
|
|
50
50
|
|
|
51
51
|
let helloPayload = connectHello;
|
|
52
|
-
if (!
|
|
52
|
+
if (!helloPayload) {
|
|
53
53
|
log("defaulting hello payload");
|
|
54
54
|
helloPayload = {
|
|
55
|
-
hello: {}
|
|
55
|
+
hello: {}
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -74,6 +74,8 @@ function _doConnect(connectHello) {
|
|
|
74
74
|
|
|
75
75
|
// Schedule the next ping.
|
|
76
76
|
_startPingTimer.call(this);
|
|
77
|
+
|
|
78
|
+
this.emit("ping", response.ping.timestamp);
|
|
77
79
|
break;
|
|
78
80
|
}
|
|
79
81
|
case "acknowledge": {
|
|
@@ -90,7 +92,7 @@ function _doConnect(connectHello) {
|
|
|
90
92
|
break;
|
|
91
93
|
}
|
|
92
94
|
case "evt": {
|
|
93
|
-
log("received event %s", response.evt
|
|
95
|
+
log("received event %s", Object.keys(response.evt)[0]);
|
|
94
96
|
this.emit("evt", response.evt);
|
|
95
97
|
break;
|
|
96
98
|
}
|
|
@@ -134,7 +136,7 @@ function _startPingTimer() {
|
|
|
134
136
|
|
|
135
137
|
this._pingTimeoutTimer = setTimeout(
|
|
136
138
|
_connectionTimeoutHandler.bind(this),
|
|
137
|
-
this._timeoutInterval
|
|
139
|
+
this._timeoutInterval
|
|
138
140
|
);
|
|
139
141
|
}, this._pingInterval);
|
|
140
142
|
}
|