@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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.14.134",
6
+ "version": "0.15.1",
7
7
  "description": "tdx Volt library for nodejs clients",
8
8
  "type": "module",
9
9
  "exports": {
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
  }
@@ -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
- // This indicates the client has finished sending payloads.
128
- // We don't need to do anything here, since we notify the client when we receive the client_end.
129
- log("method_end received");
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
  }
@@ -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
  }
@@ -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 (!connectHello) {
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.event_type);
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
  }