@tdxvolt/volt-client-grpc 0.14.60 → 0.14.134

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 CHANGED
@@ -462,7 +462,7 @@ var grpcUtils = /*#__PURE__*/Object.freeze({
462
462
  /* eslint-disable no-underscore-dangle */
463
463
 
464
464
  const { pki: pki$1 } = forge__default["default"];
465
- const log$4 = debug__default["default"]("volt-client-grpc:volt-credential");
465
+ const log$5 = debug__default["default"]("volt-client-grpc:volt-credential");
466
466
  const aesAlgorithm = "aes-256-cbc";
467
467
  const rs256Algorithm = "RS256";
468
468
 
@@ -523,6 +523,18 @@ class VoltCredential {
523
523
  return this._cryptoCache;
524
524
  }
525
525
 
526
+ get clientId() {
527
+ return this._cryptoCache.client_id;
528
+ }
529
+
530
+ get voltPublicKey() {
531
+ return this._voltPublicKey;
532
+ }
533
+
534
+ get publicKey() {
535
+ return pki$1.publicKeyToPem(this.getKey().publicKey);
536
+ }
537
+
526
538
  get voltFingerprint() {
527
539
  return this._voltFingerprint;
528
540
  }
@@ -539,17 +551,17 @@ class VoltCredential {
539
551
  createKey() {
540
552
  if (this._cryptoCache.key) {
541
553
  // Already have key data in the cache in pem format => create fully-formed pki instances.
542
- log$4("createKey - key already exists");
554
+ log$5("createKey - key already exists");
543
555
  return Promise.resolve(this.getKey());
544
556
  } else {
545
- log$4("creating key");
557
+ log$5("creating key");
546
558
  return new Promise((resolve, reject) => {
547
559
  pki$1.rsa.generateKeyPair({ bits: 2048, workers: -1 }, (err, keypair) => {
548
560
  if (err) {
549
- log$4("failure creating key [%s]", err.message);
561
+ log$5("failure creating key [%s]", err.message);
550
562
  reject(err);
551
563
  } else {
552
- log$4("successfully created key");
564
+ log$5("successfully created key");
553
565
  const pem = pki$1.privateKeyToPem(keypair.privateKey);
554
566
  this._cryptoCache.key = pem;
555
567
  resolve(keypair);
@@ -571,7 +583,7 @@ class VoltCredential {
571
583
  return this._cryptoCache;
572
584
  })
573
585
  .catch((err) => {
574
- log$4("failure initialising crypto [%s]", err.message);
586
+ log$5("failure initialising crypto [%s]", err.message);
575
587
  return Promise.reject(err);
576
588
  });
577
589
  }
@@ -586,7 +598,7 @@ class VoltCredential {
586
598
  * @param {*} tunnelling flag indicating if the token is required for a tunnelled connection
587
599
  * @param {*} ttl time to live in seconds (default to 1 minute)
588
600
  */
589
- getIdentityToken(audience, tunnelling = false, ttl = 60) {
601
+ getIdentityToken(audience, publicKey, tunnelling = false, ttl = 60) {
590
602
  if (!this._cryptoCache.key) {
591
603
  throw new Error("crypto cache invalid");
592
604
  }
@@ -595,7 +607,7 @@ class VoltCredential {
595
607
  const publicKeyPem = pki$1.publicKeyToPem(keyPair.publicKey);
596
608
  const base58Key = createPublicKeyFingerprint(publicKeyPem);
597
609
 
598
- log$4("base58 key is %s", base58Key);
610
+ log$5("base58 key is %s", base58Key);
599
611
 
600
612
  // Allow TTL either side of the current time.
601
613
  // @todo - fix with server time sync on volt connection.
@@ -612,11 +624,8 @@ class VoltCredential {
612
624
  sharedKey = VoltCredential.aesCreateKey();
613
625
 
614
626
  // Encrypt the key details using the target Volt public key and include this in the JWT payload.
615
- payload.sk = VoltCredential.rsaEncrypt(
616
- this._voltPublicKey,
617
- sharedKey.key,
618
- );
619
- payload.iv = VoltCredential.rsaEncrypt(this._voltPublicKey, sharedKey.iv);
627
+ payload.sk = VoltCredential.rsaEncrypt(publicKey, sharedKey.key);
628
+ payload.iv = VoltCredential.rsaEncrypt(publicKey, sharedKey.iv);
620
629
  }
621
630
 
622
631
  // Sign synchronously.
@@ -641,9 +650,10 @@ class VoltCredential {
641
650
  * @param {*} ttl
642
651
  * @returns
643
652
  */
644
- getIdentityMetadata(grpc, audience, tunnelling = false, ttl = 60) {
653
+ getIdentityMetadata(grpc, audience, publicKey, tunnelling = false, ttl = 60) {
645
654
  const identityToken = this.getIdentityToken(
646
655
  audience || this._voltConfig.id,
656
+ publicKey,
647
657
  tunnelling,
648
658
  ttl,
649
659
  );
@@ -689,6 +699,12 @@ class VoltCredential {
689
699
  static rsaEncrypt(key, buffer) {
690
700
  return crypto__default["default"].publicEncrypt(key, buffer).toString("base64");
691
701
  }
702
+
703
+ static rsaDecrypt(key, buffer) {
704
+ const keyObj = crypto__default["default"].createPrivateKey(key);
705
+ const cipher = Buffer.from(buffer, "base64");
706
+ return Buffer.from(crypto__default["default"].privateDecrypt(keyObj, cipher));
707
+ }
692
708
  }
693
709
 
694
710
  const { get: getProp, snakeCase } = lodash__default["default"];
@@ -705,23 +721,23 @@ const defaultLoaderOptions = {
705
721
  includeDirs: [defaultProtoPath],
706
722
  };
707
723
 
708
- const getProtoDescriptors = (grpc, protoPath, opts) => {
724
+ function getProtoDescriptors(grpc, protoPath, opts) {
709
725
  const definition = protoLoader__default["default"].loadSync(
710
726
  protoPath,
711
727
  opts || defaultLoaderOptions,
712
728
  );
713
729
  const descriptors = grpc.loadPackageDefinition(definition);
714
730
  return descriptors;
715
- };
731
+ }
716
732
 
717
- const getProtoService = (descriptors, servicePath) => {
733
+ function getProtoService(descriptors, servicePath) {
718
734
  const serviceDef = getProp(descriptors, servicePath);
719
735
  if (serviceDef?.service) {
720
736
  return serviceDef.service;
721
737
  } else {
722
738
  return null;
723
739
  }
724
- };
740
+ }
725
741
 
726
742
  function getServiceDescriptorsFromPath(
727
743
  grpc,
@@ -729,8 +745,30 @@ function getServiceDescriptorsFromPath(
729
745
  servicePackageName,
730
746
  opts,
731
747
  ) {
748
+ if (!opts) {
749
+ opts = { ...defaultLoaderOptions };
750
+ opts.includeDirs = [protoPath];
751
+ }
752
+
753
+ // Extract the package components of the service proto package. The package name should be of the
754
+ // fully qualified proto path, e.g. tdx.volt_api.webcam.v1.WebcamControlAPI.
755
+ const protoServiceComponents = servicePackageName.split(".");
756
+
757
+ // The service name is the last component of the path.
758
+ const protoServiceName = protoServiceComponents.pop();
759
+
760
+ // The actual file name should match the snake case of the service name.
761
+ const protoFileName = `${snakeCase(protoServiceName).toLowerCase()}.proto`;
762
+
763
+ // The path to the proto file should match each component of the package name.
764
+ const serviceProtoPath = path.join(
765
+ protoPath,
766
+ ...protoServiceComponents,
767
+ protoFileName,
768
+ );
769
+
732
770
  let serviceDescriptors;
733
- const descriptors = getProtoDescriptors(grpc, protoPath, opts);
771
+ const descriptors = getProtoDescriptors(grpc, serviceProtoPath, opts);
734
772
  if (descriptors) {
735
773
  serviceDescriptors = getProtoService(descriptors, servicePackageName);
736
774
  }
@@ -778,8 +816,17 @@ function getProtoDescriptorMethods(protoDescriptor) {
778
816
  return methods;
779
817
  }
780
818
 
819
+ function createServiceProtobufFiles(service, protoPath) {
820
+ for (let protoFile of service.service_description.proto_file) {
821
+ const filePath = path.join(protoPath, protoFile.file_path);
822
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
823
+ fs.writeFileSync(filePath, protoFile.protobuf);
824
+ }
825
+ }
826
+
781
827
  var protoUtils = /*#__PURE__*/Object.freeze({
782
828
  __proto__: null,
829
+ createServiceProtobufFiles: createServiceProtobufFiles,
783
830
  getServiceDescriptors: getServiceDescriptors,
784
831
  getProtoDescriptors: getProtoDescriptors,
785
832
  getProtoDescriptorMethods: getProtoDescriptorMethods,
@@ -788,70 +835,101 @@ var protoUtils = /*#__PURE__*/Object.freeze({
788
835
 
789
836
  /* eslint-disable no-underscore-dangle */
790
837
 
791
- const log$3 = debug__default["default"]("volt-client-grpc:grpc-call");
838
+ const log$4 = debug__default["default"]("volt-client-grpc:grpc-call");
792
839
 
793
840
  function _prepareInvokeRequest(
794
841
  request,
795
842
  method,
796
843
  methodType = "METHOD_TYPE_UNARY",
797
844
  ) {
798
- const meta = this._voltClient.credential.getIdentityMetadata(
845
+ const isServiceRelayed =
846
+ this._service?.service_description.host_type ===
847
+ "SERVICE_HOST_TYPE_RELAYED";
848
+
849
+ // Use the service's host client id and public key if the service is relayed.
850
+ const methodToken = this._voltClient.credential.getIdentityMetadata(
799
851
  this._voltClient.grpc,
800
- this._voltClient.voltConfig.id,
801
- this._voltClient.isRemote,
852
+ this._service?.service_description.host_client_id ||
853
+ this._voltClient.voltConfig.id,
854
+ this._service?.service_description.host_public_key ||
855
+ this._voltClient.credential.voltPublicKey,
856
+ true,
802
857
  );
858
+
803
859
  let invokeRequest;
804
860
  let callMethod = method;
805
861
 
806
- if (this._voltClient.isVoltRelay) {
862
+ if (this._voltClient.isVoltRelay || isServiceRelayed) {
863
+ //
864
+ // If the volt connection is via a relay (or the target service is relayed),
865
+ // we wrap the rpc in a RemoteRequest message and send it via a call to Invoke().
866
+ //
807
867
  let requestPayload;
868
+
869
+ // Serialise the rpc request.
808
870
  if (request) {
809
871
  requestPayload = this._grpcClient[method].requestSerialize(request);
810
872
  } else if (request !== null) {
811
- log$3("****************LOOKOUT****************** - empty request");
873
+ log$4("****************LOOKOUT****************** - empty request");
812
874
  } else {
813
- log$3("explicit empty request payload");
875
+ log$4("explicit empty request payload");
814
876
  }
815
877
 
816
- const tunnelMethod = this._grpcClient.Tunnel;
878
+ // Use this placeholder to serialise the relay request wrapper.
879
+ const voltGrpcClient = this._voltClient.getVoltAPIClient();
880
+ const tunnelMethod = voltGrpcClient.Tunnel;
817
881
 
818
882
  const tunnelResp = {
819
883
  method_invoke: {
820
884
  method_name: this._grpcClient[method].path,
821
885
  method_type: methodType,
822
- token: meta.token,
886
+ token: methodToken.token,
823
887
  request: requestPayload,
824
888
  },
825
889
  };
826
890
 
827
- const invokePayload = VoltCredential.aesEncrypt(
828
- tunnelMethod.responseSerialize(tunnelResp),
829
- meta.sharedKey.key,
830
- meta.sharedKey.iv,
831
- );
891
+ let targetFingerprint = [];
892
+ let invokePayload;
893
+ if (this._voltClient.isVoltRelay || isServiceRelayed) {
894
+ // When sending via a relay we need to encrypt the payload.
895
+ invokePayload = VoltCredential.aesEncrypt(
896
+ tunnelMethod.responseSerialize(tunnelResp),
897
+ methodToken.sharedKey.key,
898
+ methodToken.sharedKey.iv,
899
+ );
900
+ } else {
901
+ invokePayload = tunnelMethod.responseSerialize(tunnelResp);
902
+ }
903
+
904
+ if (this._voltClient.isVoltRelay) {
905
+ targetFingerprint.push(this._voltClient.credential.voltFingerprint);
906
+ }
907
+
908
+ if (isServiceRelayed) {
909
+ // Add another relay hop if the target service is relayed.
910
+ log$4("target service is relayed");
911
+ targetFingerprint.push(
912
+ this._service.service_description.host_fingerprint,
913
+ );
914
+ }
832
915
 
833
- log$3("target volt is %s", this._voltClient.credential.voltFingerprint);
916
+ log$4("target is %j", targetFingerprint);
834
917
 
835
918
  invokeRequest = {
836
- identity_fingerprint: this._voltClient.credential.voltFingerprint,
919
+ target_fingerprint: targetFingerprint,
920
+ token: methodToken.token,
837
921
  payload: invokePayload,
922
+ target_service_id: isServiceRelayed ? this._service.id : undefined,
838
923
  };
839
924
 
925
+ // Replace the target method with a call to Invoke on the relay Volt.
840
926
  callMethod = "Invoke";
841
- } else if (this._voltClient.isRemote && meta.sharedKey.key) {
842
- const requestPayload =
843
- this._grpcClient[method].requestSerializeOriginal(request);
844
- invokeRequest = VoltCredential.aesEncrypt(
845
- requestPayload,
846
- meta.sharedKey.key,
847
- meta.sharedKey.iv,
848
- );
849
927
  } else {
850
928
  invokeRequest = request;
851
929
  }
852
930
 
853
931
  return {
854
- meta,
932
+ meta: methodToken,
855
933
  method: callMethod,
856
934
  methodName: method,
857
935
  request: invokeRequest,
@@ -861,10 +939,16 @@ function _prepareInvokeRequest(
861
939
  function _preparePayloadRequest(request, invokeInfo) {
862
940
  let payloadRequest;
863
941
 
864
- if (this._voltClient.isVoltRelay) {
942
+ const isServiceRelayed =
943
+ this._service?.service_description.host_type ===
944
+ "SERVICE_HOST_TYPE_RELAYED";
945
+
946
+ if (this._voltClient.isVoltRelay || isServiceRelayed) {
865
947
  const requestPayload =
866
948
  this._grpcClient[invokeInfo.methodName].requestSerialize(request);
867
- const tunnelMethod = this._grpcClient.Tunnel;
949
+
950
+ const voltGrpcClient = this._voltClient.getVoltAPIClient();
951
+ const tunnelMethod = voltGrpcClient.Tunnel;
868
952
 
869
953
  const tunnelResp = {
870
954
  method_payload: {
@@ -881,14 +965,6 @@ function _preparePayloadRequest(request, invokeInfo) {
881
965
  payloadRequest = {
882
966
  payload: invokePayload,
883
967
  };
884
- } else if (this._voltClient.isRemote && invokeInfo.meta.sharedKey.key) {
885
- const requestPayload =
886
- this._grpcClient[invokeInfo.methodName].requestSerializeOriginal(request);
887
- payloadRequest = VoltCredential.aesEncrypt(
888
- requestPayload,
889
- invokeInfo.meta.sharedKey.key,
890
- invokeInfo.meta.sharedKey.iv,
891
- );
892
968
  } else {
893
969
  payloadRequest = request;
894
970
  }
@@ -897,29 +973,47 @@ function _preparePayloadRequest(request, invokeInfo) {
897
973
  }
898
974
 
899
975
  function _parseResponse(method, meta, response) {
976
+ // log("parseResponse for %s", this._methodName);
900
977
  let invokeResponse = {};
901
978
 
902
- if (this._voltClient.isVoltRelay) {
979
+ const isServiceRelayed =
980
+ this._service?.service_description.host_type ===
981
+ "SERVICE_HOST_TYPE_RELAYED";
982
+
983
+ if (this._voltClient.isVoltRelay || isServiceRelayed) {
903
984
  if (response.payload) {
904
- const decryptedPayload = VoltCredential.aesDecrypt(
905
- response.payload,
906
- meta.sharedKey.key,
907
- meta.sharedKey.iv,
908
- );
909
- const tunnelMethod = this._grpcClient.Tunnel;
985
+ let decryptedPayload;
986
+ if (meta.sharedKey.key) {
987
+ decryptedPayload = VoltCredential.aesDecrypt(
988
+ response.payload,
989
+ meta.sharedKey.key,
990
+ meta.sharedKey.iv,
991
+ );
992
+ } else {
993
+ decryptedPayload = response.payload;
994
+ }
995
+
996
+ const tunnelMethod = this._voltClient.getVoltAPIClient().Tunnel;
910
997
  const responsePayload = tunnelMethod.requestDeserialize(decryptedPayload);
911
998
  if (responsePayload.payload === "method_payload") {
912
- invokeResponse.payload = this._grpcClient[method].responseDeserialize(
913
- responsePayload.method_payload.payload,
914
- );
999
+ try {
1000
+ invokeResponse.payload = this._grpcClient[method].responseDeserialize(
1001
+ responsePayload.method_payload.payload,
1002
+ );
1003
+ } catch (err) {
1004
+ log$4("failure deserialising payload for %s", this._methodName);
1005
+ throw new Error(
1006
+ "failure deserialising payload - check protobuf definition matches with data being sent",
1007
+ );
1008
+ }
915
1009
  } else if (responsePayload.payload === "method_end") {
916
1010
  invokeResponse = responsePayload.method_end;
917
1011
  } else {
918
- log$3("unexpected tunnel payload type: %s", responsePayload.payload);
1012
+ log$4("unexpected tunnel payload type: %s", responsePayload.payload);
919
1013
  }
920
1014
  } else if (response.status?.message) {
921
1015
  // There's been an error in the tunnel.
922
- log$3(
1016
+ log$4(
923
1017
  "Tunnel status received: %s, code %d, description: %s",
924
1018
  response.status.message,
925
1019
  response.status.code,
@@ -931,7 +1025,7 @@ function _parseResponse(method, meta, response) {
931
1025
  };
932
1026
  } else {
933
1027
  invokeResponse.methodId = response.invoke_id;
934
- log$3("started method %d for %s", invokeResponse.methodId, method);
1028
+ log$4("started method %d for %s", invokeResponse.methodId, method);
935
1029
  }
936
1030
  } else if (this._voltClient.isRemote && meta.sharedKey.key) {
937
1031
  const decryptedPayload = VoltCredential.aesDecrypt(
@@ -951,17 +1045,22 @@ function _parseResponse(method, meta, response) {
951
1045
  }
952
1046
 
953
1047
  class GRPCCall extends EventEmitter__default["default"] {
954
- constructor(voltClient, methodName, methodType) {
1048
+ constructor(voltClient, methodName, methodType, service = undefined) {
955
1049
  super();
956
1050
  this._methodName = methodName;
957
1051
  this._methodType = methodType;
958
1052
  this._call = null;
959
1053
  this._voltClient = voltClient;
1054
+ this._service = service;
960
1055
  }
961
1056
 
962
1057
  start(grpcClient, request) {
963
1058
  this._grpcClient = grpcClient;
964
1059
 
1060
+ if (typeof this._grpcClient[this._methodName] !== "function") {
1061
+ throw new Error(`method not found: '${this._methodName}'`);
1062
+ }
1063
+
965
1064
  this._initialRequest = _prepareInvokeRequest.call(
966
1065
  this,
967
1066
  request,
@@ -969,13 +1068,18 @@ class GRPCCall extends EventEmitter__default["default"] {
969
1068
  this._methodType,
970
1069
  );
971
1070
 
972
- if (!this._grpcClient[this._initialRequest.method]) {
973
- return reject(
974
- new Error(`method not found: '${this._initialRequest.method}'`),
975
- );
1071
+ const isServiceRelayed =
1072
+ this._service?.service_description.host_type ===
1073
+ "SERVICE_HOST_TYPE_RELAYED";
1074
+
1075
+ let callClient;
1076
+ if (this._voltClient.isVoltRelay || isServiceRelayed) {
1077
+ callClient = this._voltClient.getVoltAPIClient();
1078
+ } else {
1079
+ callClient = this._grpcClient;
976
1080
  }
977
1081
 
978
- this._call = this._grpcClient[this._initialRequest.method](
1082
+ this._call = callClient[this._initialRequest.method](
979
1083
  this._initialRequest.meta.metadata,
980
1084
  );
981
1085
 
@@ -1005,28 +1109,32 @@ class GRPCCall extends EventEmitter__default["default"] {
1005
1109
  this.emit("end");
1006
1110
  }
1007
1111
  } else {
1008
- log$3("method id is %s", parsedResponse.methodId);
1112
+ log$4("method id is %s", parsedResponse.methodId);
1009
1113
  }
1010
1114
  } catch (err) {
1011
- log$3("failure processing connect response: %s", err.message);
1115
+ log$4(
1116
+ "failure processing %s call response: %s",
1117
+ this._methodName,
1118
+ err.message,
1119
+ );
1012
1120
  this.emit("error", err);
1013
1121
  }
1014
1122
  });
1015
1123
 
1016
1124
  this._call.on("error", (err) => {
1017
- log$3("ERROR - intercepted stream error %s", err.message);
1125
+ log$4("ERROR - intercepted stream error %s", err.message);
1018
1126
  this.emit("error", err);
1019
1127
  });
1020
1128
 
1021
1129
  this._call.on("finish", () => {
1022
1130
  // The read side has ended (i.e. we called end()).
1023
- log$3("finished call %s", this._methodName);
1131
+ log$4("finished call %s", this._methodName);
1024
1132
  this.emit("finish");
1025
1133
  });
1026
1134
 
1027
1135
  this._call.on("end", () => {
1028
1136
  // The remote peer ended the stream.
1029
- log$3(
1137
+ log$4(
1030
1138
  "ended call %s, method id: %s",
1031
1139
  this._methodName,
1032
1140
  this._initialRequest.methodId || "n/a - not tunnelling",
@@ -1056,7 +1164,7 @@ class GRPCCall extends EventEmitter__default["default"] {
1056
1164
 
1057
1165
  write(request) {
1058
1166
  if (!this._call) {
1059
- log$3("ERROR - call not initialised");
1167
+ log$4("ERROR - call not initialised");
1060
1168
  throw new Error("call not initialised");
1061
1169
  } else if (this._initialRequest) {
1062
1170
  const payloadRequest = _preparePayloadRequest.call(
@@ -1080,7 +1188,7 @@ class GRPCCall extends EventEmitter__default["default"] {
1080
1188
 
1081
1189
  /* eslint-disable no-use-before-define */
1082
1190
 
1083
- const log$2 = debug__default["default"]("volt-client-grpc:volt-connection");
1191
+ const log$3 = debug__default["default"]("volt-client-grpc:volt-connection");
1084
1192
 
1085
1193
  function _cleanUp(immediateReconnect) {
1086
1194
  this._connectionId = "";
@@ -1114,7 +1222,7 @@ function _cleanUp(immediateReconnect) {
1114
1222
  }
1115
1223
 
1116
1224
  function _connectionTimeoutHandler() {
1117
- log$2("server timed out");
1225
+ log$3("server timed out");
1118
1226
  this.emit("connected", false);
1119
1227
  _cleanUp.call(this);
1120
1228
  }
@@ -1126,14 +1234,14 @@ function _doConnect(connectHello) {
1126
1234
 
1127
1235
  let helloPayload = connectHello;
1128
1236
  if (!connectHello) {
1129
- log$2("defaulting hello payload");
1237
+ log$3("defaulting hello payload");
1130
1238
  helloPayload = {
1131
1239
  hello: {},
1132
1240
  };
1133
1241
  }
1134
1242
 
1135
1243
  this.call.on("error", (err) => {
1136
- log$2("error on connection stream [%s]", err.message);
1244
+ log$3("error on connection stream [%s]", err.message);
1137
1245
  _cleanUp.call(this);
1138
1246
  this.emit("error", err);
1139
1247
  });
@@ -1141,7 +1249,7 @@ function _doConnect(connectHello) {
1141
1249
  this.call.on("data", (response) => {
1142
1250
  switch (response.payload) {
1143
1251
  case "ping": {
1144
- log$2("pinged");
1252
+ log$3("pinged");
1145
1253
 
1146
1254
  // Received ping response from server => clear timeout.
1147
1255
  if (this._pingTimeoutTimer) {
@@ -1155,18 +1263,23 @@ function _doConnect(connectHello) {
1155
1263
  case "acknowledge": {
1156
1264
  if (!this._connectionId) {
1157
1265
  this._connectionId = response.acknowledge.connection_id;
1158
- log$2("connection id is %s", this._connectionId);
1266
+ log$3("connection id is %s", this._connectionId);
1159
1267
  this.emit("connected", this._connectionId);
1160
1268
  }
1161
1269
  break;
1162
1270
  }
1271
+ case "invoke_request": {
1272
+ log$3("received invoke request");
1273
+ this.emit("invoke_request", response.invoke_request);
1274
+ break;
1275
+ }
1163
1276
  case "evt": {
1164
- log$2("received event %s", response.evt.event_type);
1277
+ log$3("received event %s", response.evt.event_type);
1165
1278
  this.emit("evt", response.evt);
1166
1279
  break;
1167
1280
  }
1168
1281
  default:
1169
- log$2("unimplemented connect response payload: %s", response.payload);
1282
+ log$3("unimplemented connect response payload: %s", response.payload);
1170
1283
  break;
1171
1284
  }
1172
1285
  });
@@ -1185,7 +1298,7 @@ function _doConnect(connectHello) {
1185
1298
 
1186
1299
  function _startPingTimer() {
1187
1300
  if (this._pingTimer) {
1188
- log$2("ping timer running");
1301
+ log$3("ping timer running");
1189
1302
  return;
1190
1303
  }
1191
1304
 
@@ -1193,7 +1306,7 @@ function _startPingTimer() {
1193
1306
  // Send next ping to server.
1194
1307
  const request = { ping: { timestamp: Date.now() } };
1195
1308
 
1196
- log$2("pinging Volt");
1309
+ log$3("pinging Volt");
1197
1310
  this.call.write(request);
1198
1311
 
1199
1312
  this._pingTimer = 0;
@@ -1242,6 +1355,277 @@ class VoltConnection extends EventEmitter__default["default"] {
1242
1355
  this._dying = true;
1243
1356
  _cleanUp.call(this);
1244
1357
  }
1358
+
1359
+ send(request) {
1360
+ this.call.write(request);
1361
+ }
1362
+ }
1363
+
1364
+ const log$2 = debug__default["default"]("rpc-invocation");
1365
+
1366
+ class RpcInvocation extends EventEmitter__default["default"] {
1367
+ #voltClient = null;
1368
+ #voltConnection = null;
1369
+ #token = null;
1370
+ #encryptKey = null;
1371
+ #encryptIV = null;
1372
+ #invokeId = null;
1373
+ #payload = null;
1374
+ #isJSON = false;
1375
+ #methodDescriptor = null;
1376
+ #methodName = null;
1377
+
1378
+ constructor(voltClient, voltConnection) {
1379
+ super();
1380
+ this.#voltClient = voltClient;
1381
+ this.#voltConnection = voltConnection;
1382
+ }
1383
+
1384
+ get id() {
1385
+ return this.#invokeId;
1386
+ }
1387
+
1388
+ get payload() {
1389
+ if (!this.#payload) {
1390
+ return null;
1391
+ }
1392
+
1393
+ let deserialisedPayload = null;
1394
+
1395
+ if (this.#isJSON) {
1396
+ // Don't need to deserialise JSON payload.
1397
+ deserialisedPayload = this.#payload;
1398
+ } else if (this.#methodDescriptor) {
1399
+ deserialisedPayload = this.#methodDescriptor.requestDeserialize(
1400
+ this.#payload,
1401
+ );
1402
+ } else {
1403
+ log$2("unexpected: no method descriptor");
1404
+ throw new Error(
1405
+ "no method descriptor - set this before accessing payload",
1406
+ );
1407
+ }
1408
+
1409
+ return deserialisedPayload;
1410
+ }
1411
+
1412
+ get methodName() {
1413
+ return this.#methodName;
1414
+ }
1415
+
1416
+ set methodDescriptor(methodDescriptor) {
1417
+ this.#methodDescriptor = methodDescriptor;
1418
+ }
1419
+
1420
+ #decodeToken(token) {
1421
+ // We don't verify the token at this point, as we don't know the public key.
1422
+ // The rpc implementation should do the verification using the Volt API (e.g. CanAccessResource).
1423
+ this.#token = jwt__default["default"].decode(token);
1424
+
1425
+ if (this.#token.sk) {
1426
+ // Decrypt the shared key and iv using the private key.
1427
+ this.#encryptKey = VoltCredential.rsaDecrypt(
1428
+ this.#voltClient.credential.cache.key,
1429
+ this.#token.sk,
1430
+ );
1431
+ this.#encryptIV = VoltCredential.rsaDecrypt(
1432
+ this.#voltClient.credential.cache.key,
1433
+ this.#token.iv,
1434
+ );
1435
+ }
1436
+
1437
+ return Promise.resolve(this.#token);
1438
+ }
1439
+
1440
+ initialise(invoke_request) {
1441
+ this.#invokeId = invoke_request.invoke_id;
1442
+
1443
+ return this.#decodeToken(invoke_request.token)
1444
+ .then(() => {
1445
+ // Parse the initial payload.
1446
+ return this.parsePayload(invoke_request);
1447
+ })
1448
+ .catch((err) => {
1449
+ log$2("failure initialising invocation: %s", err.message);
1450
+ return Promise.reject(err);
1451
+ });
1452
+ }
1453
+
1454
+ parsePayload(invoke_request) {
1455
+ return new Promise((resolve, reject) => {
1456
+ if (invoke_request.payload) {
1457
+ let decryptedPayload;
1458
+
1459
+ if (this.#encryptKey) {
1460
+ // Decrypt the actual payload using the shared key and iv.
1461
+ decryptedPayload = VoltCredential.aesDecrypt(
1462
+ invoke_request.payload,
1463
+ this.#encryptKey,
1464
+ this.#encryptIV,
1465
+ );
1466
+ } else {
1467
+ // No encryption => just use the payload.
1468
+ decryptedPayload = invoke_request.payload;
1469
+ }
1470
+
1471
+ const tunnelMethod = this.#voltClient.getVoltAPIClient().Tunnel;
1472
+ const wrappedPayload =
1473
+ tunnelMethod.responseDeserialize(decryptedPayload);
1474
+
1475
+ if (wrappedPayload.method_invoke) {
1476
+ // This is the initial request payload.
1477
+ this.#methodName = wrappedPayload.method_invoke.method_name;
1478
+ this.#payload = wrappedPayload.method_invoke.request;
1479
+ this.emit("payload", this);
1480
+ } else if (wrappedPayload.method_payload) {
1481
+ // This is a subsequent payload, e.g. for streaming rpcs.
1482
+ this.#payload = wrappedPayload.method_payload.payload;
1483
+ this.emit("payload", this);
1484
+ } else if (wrappedPayload.method_end) {
1485
+ // This indicates the client has finished sending payloads.
1486
+ // We don't need to do anything here, since we notify the client when we receive the client_end.
1487
+ log$2("method_end received");
1488
+ }
1489
+
1490
+ resolve();
1491
+ } else if (invoke_request.json_payload) {
1492
+ let decryptedPayload;
1493
+
1494
+ this.#isJSON = true;
1495
+
1496
+ if (this.#encryptKey) {
1497
+ // Decrypt the actual payload using the shared key and iv.
1498
+ decryptedPayload = VoltCredential.aesDecrypt(
1499
+ Buffer.from(invoke_request.json_payload, "base64"),
1500
+ this.#encryptKey,
1501
+ this.#encryptIV,
1502
+ );
1503
+ } else {
1504
+ // No encryption => just use the payload.
1505
+ decryptedPayload = invoke_request.json_payload;
1506
+ }
1507
+
1508
+ try {
1509
+ const wrappedPayload = JSON.parse(decryptedPayload.toString());
1510
+
1511
+ if (wrappedPayload.method_invoke) {
1512
+ this.#methodName = wrappedPayload.method_invoke.method_name;
1513
+ this.#payload = JSON.parse(
1514
+ wrappedPayload.method_invoke.json_request,
1515
+ );
1516
+ this.emit("payload", this);
1517
+ } else if (wrappedPayload.method_payload) {
1518
+ this.#payload = JSON.parse(
1519
+ wrappedPayload.method_payload.json_payload,
1520
+ );
1521
+ this.emit("payload", this);
1522
+ } else if (wrappedPayload.method_end) {
1523
+ // We don't need to do anything here, since we notify the client when we receive the client_end.
1524
+ log$2("method_end received");
1525
+ }
1526
+ } catch (err) {
1527
+ log$2("JSON.parse failure parsing json_payload: %s", err.message);
1528
+ reject(err);
1529
+ }
1530
+
1531
+ resolve();
1532
+ } else if (invoke_request.client_end) {
1533
+ this.emit("end", this);
1534
+ } else {
1535
+ // Do we need to support json_payload here?
1536
+ reject(new Error("No payload in invoke request"));
1537
+ }
1538
+ }).catch((err) => {
1539
+ log$2("failure parsing payload: %s", err.message);
1540
+ return Promise.reject(err);
1541
+ });
1542
+ }
1543
+
1544
+ sendResponse(response) {
1545
+ let responsePayload;
1546
+ if (this.#isJSON) {
1547
+ responsePayload = JSON.stringify({
1548
+ method_payload: { json_payload: JSON.stringify(response) },
1549
+ });
1550
+ } else {
1551
+ // We need to serialise the response, and then wrap it in a RemoteRequest.
1552
+ const serialisedResponse =
1553
+ this.#methodDescriptor.responseSerialize(response);
1554
+ const tunnelMethod = this.#voltClient.getVoltAPIClient().Tunnel;
1555
+ responsePayload = tunnelMethod.requestSerialize({
1556
+ method_payload: { payload: serialisedResponse },
1557
+ });
1558
+ }
1559
+
1560
+ if (this.#token.sk) {
1561
+ // Encrypt the response using the shared key and iv.
1562
+ responsePayload = VoltCredential.aesEncrypt(
1563
+ responsePayload,
1564
+ this.#encryptKey,
1565
+ this.#encryptIV,
1566
+ );
1567
+ }
1568
+
1569
+ const invokeResponse = {
1570
+ invoke_id: this.#invokeId,
1571
+ };
1572
+
1573
+ if (this.#isJSON) {
1574
+ invokeResponse.json_payload =
1575
+ Buffer.from(responsePayload).toString("base64");
1576
+ } else {
1577
+ invokeResponse.payload = responsePayload;
1578
+ }
1579
+
1580
+ this.#voltConnection.send({
1581
+ invoke_response: invokeResponse,
1582
+ });
1583
+ }
1584
+
1585
+ sendEnd(errorMessage) {
1586
+ const tunnelMethod = this.#voltClient.getVoltAPIClient().Tunnel;
1587
+
1588
+ let endPayload;
1589
+ if (errorMessage) {
1590
+ endPayload = {
1591
+ method_end: { error: errorMessage, ended: true },
1592
+ };
1593
+ } else {
1594
+ endPayload = {
1595
+ method_end: { ended: true },
1596
+ };
1597
+ }
1598
+
1599
+ if (this.#isJSON) {
1600
+ endPayload = JSON.stringify(endPayload);
1601
+ } else {
1602
+ endPayload = tunnelMethod.requestSerialize(endPayload);
1603
+ }
1604
+
1605
+ if (this.#token.sk) {
1606
+ // Encrypt the response using the shared key and iv.
1607
+ endPayload = VoltCredential.aesEncrypt(
1608
+ endPayload,
1609
+ this.#encryptKey,
1610
+ this.#encryptIV,
1611
+ );
1612
+ }
1613
+
1614
+ const invokeResponse = {
1615
+ invoke_id: this.#invokeId,
1616
+ server_end: true,
1617
+ };
1618
+
1619
+ if (this.#isJSON) {
1620
+ invokeResponse.json_payload = Buffer.from(endPayload).toString("base64");
1621
+ } else {
1622
+ invokeResponse.payload = endPayload;
1623
+ }
1624
+
1625
+ this.#voltConnection.send({
1626
+ invoke_response: invokeResponse,
1627
+ });
1628
+ }
1245
1629
  }
1246
1630
 
1247
1631
  /* eslint-disable no-underscore-dangle */
@@ -1262,46 +1646,48 @@ const voltServices = [
1262
1646
 
1263
1647
  function issueBind(bindRequest, ttl) {
1264
1648
  // eslint-disable-next-line no-use-before-define
1265
- return unaryCall.call(this, "Bind", bindRequest).then((bindResponse) => {
1266
- log$1("got binding request response %j", bindResponse);
1267
- if (bindResponse.status?.code) {
1268
- log$1("error in bind response: %s", bindResponse.status.message);
1269
- return Promise.reject(new Error(bindResponse.status.message));
1270
- } else {
1271
- switch (bindResponse.decision) {
1272
- case "POLICY_DECISION_PERMIT": {
1273
- //
1274
- // The request status is permit => cache the bind response info.
1275
- //
1276
-
1277
- // This is the certificate assigned to us by the volt.
1278
- this._credential.cache.cert = bindResponse.cert;
1279
-
1280
- // This is the signing CA used by the volt.
1281
- this._credential.cache.ca = bindResponse.chain;
1282
-
1283
- // Identity resource id is assigned by the volt.
1284
- this._credential.cache.client_id = bindResponse.identity_id;
1285
- this._credential.saveCache();
1286
- break;
1287
- }
1288
- case "POLICY_DECISION_DENY": {
1289
- log$1(">>>>>>>>>>>>>>> access request is DENIED <<<<<<<<<<<<<<<<<<<");
1290
- break;
1291
- }
1292
- case "POLICY_DECISION_PROMPT":
1293
- case "POLICY_DECISION_PENDING": {
1294
- log$1("access pending approval - waiting...");
1295
- break;
1649
+ return unaryCallInternal
1650
+ .call(this, "Bind", bindRequest)
1651
+ .then((bindResponse) => {
1652
+ log$1("got binding request response %j", bindResponse);
1653
+ if (bindResponse.status?.code) {
1654
+ log$1("error in bind response: %s", bindResponse.status.message);
1655
+ return Promise.reject(new Error(bindResponse.status.message));
1656
+ } else {
1657
+ switch (bindResponse.decision) {
1658
+ case "POLICY_DECISION_PERMIT": {
1659
+ //
1660
+ // The request status is permit => cache the bind response info.
1661
+ //
1662
+
1663
+ // This is the certificate assigned to us by the volt.
1664
+ this._credential.cache.cert = bindResponse.cert;
1665
+
1666
+ // This is the signing CA used by the volt.
1667
+ this._credential.cache.ca = bindResponse.chain;
1668
+
1669
+ // Identity resource id is assigned by the volt.
1670
+ this._credential.cache.client_id = bindResponse.identity_id;
1671
+ this._credential.saveCache();
1672
+ break;
1673
+ }
1674
+ case "POLICY_DECISION_DENY": {
1675
+ log$1(">>>>>>>>>>>>>>> access request is DENIED <<<<<<<<<<<<<<<<<<<");
1676
+ break;
1677
+ }
1678
+ case "POLICY_DECISION_PROMPT":
1679
+ case "POLICY_DECISION_PENDING": {
1680
+ log$1("access pending approval - waiting...");
1681
+ break;
1682
+ }
1683
+ default:
1684
+ log$1("ignoring unknown bind descision %s", bindResponse.status);
1685
+ break;
1296
1686
  }
1297
- default:
1298
- log$1("ignoring unknown bind descision %s", bindResponse.status);
1299
- break;
1300
1687
  }
1301
- }
1302
1688
 
1303
- return bindResponse.decision;
1304
- });
1689
+ return bindResponse.decision;
1690
+ });
1305
1691
  }
1306
1692
 
1307
1693
  function findDIDDocumentService(document, serviceType) {
@@ -1468,6 +1854,30 @@ function connectInternal(helloPayload) {
1468
1854
  this.emit("evt", evt);
1469
1855
  });
1470
1856
 
1857
+ this._voltConnection.on("invoke_request", (invoke_request) => {
1858
+ const invokeId = invoke_request.invoke_id;
1859
+ if (this._activeRPC[invokeId]) {
1860
+ this._activeRPC[invokeId].parsePayload(invoke_request);
1861
+ } else {
1862
+ const rpcInvocation = new RpcInvocation(this, this._voltConnection);
1863
+
1864
+ rpcInvocation.on("end", () => {
1865
+ log$1("removing active RPC [%s]", invokeId);
1866
+ this._activeRPC[invokeId] = undefined;
1867
+ });
1868
+
1869
+ rpcInvocation
1870
+ .initialise(invoke_request)
1871
+ .then(() => {
1872
+ this._activeRPC[invokeId] = rpcInvocation;
1873
+ this.emit("invoke_request", rpcInvocation);
1874
+ })
1875
+ .catch((err) => {
1876
+ log$1("invoke_request - error [%s]", err.message);
1877
+ });
1878
+ }
1879
+ });
1880
+
1471
1881
  return this._voltConnection.connect(helloPayload);
1472
1882
  } catch (err) {
1473
1883
  log$1("connect - error [%s]", err.message);
@@ -1501,11 +1911,61 @@ function getVoltAPIClientInternal() {
1501
1911
  return this._cachedClient;
1502
1912
  }
1503
1913
 
1504
- function unaryCall(method, request) {
1505
- return new Promise((resolve, reject) => {
1506
- const grpcClient = this.getVoltAPIClient();
1914
+ function getAPIClientInternal(service) {
1915
+ if (!this._cachedService[service.id]) {
1916
+ service.service_description.host_type === "SERVICE_HOST_TYPE_RELAYED";
1917
+
1918
+ const serviceAddress = this.isRemote
1919
+ ? this._voltConfig.relay.address
1920
+ : service.service_description.host_address;
1921
+
1922
+ createServiceProtobufFiles(service, "./service-proto");
1923
+
1924
+ log$1("creating API service client on %s", serviceAddress);
1925
+ let serviceDescriptors = {};
1926
+ const fullProtoPath = path.join(process.cwd(), "./service-proto");
1927
+ for (let api of service.service_description.service_api) {
1928
+ const packageDescriptors = getServiceDescriptorsFromPath(
1929
+ this._grpc,
1930
+ fullProtoPath,
1931
+ api,
1932
+ );
1933
+ serviceDescriptors = { ...serviceDescriptors, ...packageDescriptors };
1934
+ }
1935
+
1936
+ this._cachedService[service.id] = createClient(
1937
+ this._grpc,
1938
+ serviceDescriptors,
1939
+ serviceAddress,
1940
+ this._credential,
1941
+ this.isRemote && !this.isVoltRelay,
1942
+ this._voltConfig?.relay?.cloud ? this._voltConfig.id : "",
1943
+ this._voltConfig?.relay?.cloud ? this._voltConfig.id : "",
1944
+ );
1945
+ }
1946
+
1947
+ return this._cachedService[service.id];
1948
+ }
1949
+
1950
+ function getServiceClient(service) {
1951
+ let grpcClient;
1952
+ if (
1953
+ service &&
1954
+ service?.service_description.host_type !== "SERVICE_HOST_TYPE_BUILTIN"
1955
+ ) {
1956
+ grpcClient = getAPIClientInternal.call(this, service);
1957
+ } else {
1958
+ grpcClient = getVoltAPIClientInternal.call(this);
1959
+ }
1507
1960
 
1508
- const call = new GRPCCall(this, method, "METHOD_TYPE_UNARY");
1961
+ return grpcClient;
1962
+ }
1963
+
1964
+ function unaryCallInternal(method, request, service) {
1965
+ const grpcClient = getServiceClient.call(this, service);
1966
+
1967
+ return new Promise((resolve, reject) => {
1968
+ const call = new GRPCCall(this, method, "METHOD_TYPE_UNARY", service);
1509
1969
 
1510
1970
  let response = null;
1511
1971
 
@@ -1533,6 +1993,16 @@ function unaryCall(method, request) {
1533
1993
  });
1534
1994
  }
1535
1995
 
1996
+ function streamingCallInternal(methodType, method, request, service) {
1997
+ const grpcClient = getServiceClient.call(this, service);
1998
+
1999
+ const call = new GRPCCall(this, method, methodType, service);
2000
+
2001
+ call.start(grpcClient, request);
2002
+
2003
+ return call;
2004
+ }
2005
+
1536
2006
  async function fetchVoltConfig(discovery_url) {
1537
2007
  try {
1538
2008
  const getJSON = bent__default["default"]("json");
@@ -1613,6 +2083,8 @@ class VoltClient extends EventEmitter__default["default"] {
1613
2083
  this._config = null;
1614
2084
  this._voltConfig = null;
1615
2085
  this._voltConnection = null;
2086
+ this._cachedService = {};
2087
+ this._activeRPC = {};
1616
2088
  }
1617
2089
 
1618
2090
  get config() {
@@ -1858,6 +2330,40 @@ class VoltClient extends EventEmitter__default["default"] {
1858
2330
  return getVoltAPIClientInternal.call(this);
1859
2331
  }
1860
2332
 
2333
+ unaryCall(method, request, service) {
2334
+ return unaryCallInternal.call(this, method, request, service);
2335
+ }
2336
+
2337
+ bidiStreamingCall(method, request, service) {
2338
+ return streamingCallInternal.call(
2339
+ this,
2340
+ "METHOD_TYPE_BIDI",
2341
+ method,
2342
+ request,
2343
+ service,
2344
+ );
2345
+ }
2346
+
2347
+ clientStreamingCall(method, request, service) {
2348
+ return streamingCallInternal.call(
2349
+ this,
2350
+ "METHOD_TYPE_CLIENT_STREAM",
2351
+ method,
2352
+ request,
2353
+ service,
2354
+ );
2355
+ }
2356
+
2357
+ serverStreamingCall(method, request, service) {
2358
+ return streamingCallInternal.call(
2359
+ this,
2360
+ "METHOD_TYPE_SERVER_STREAM",
2361
+ method,
2362
+ request,
2363
+ service,
2364
+ );
2365
+ }
2366
+
1861
2367
  /**
1862
2368
  * Request resource access.
1863
2369
  * @param {*} targetResourceId
@@ -1902,47 +2408,47 @@ class VoltClient extends EventEmitter__default["default"] {
1902
2408
  */
1903
2409
 
1904
2410
  CanAccessResource(request) {
1905
- return unaryCall.call(this, "CanAccessResource", request);
2411
+ return unaryCallInternal.call(this, "CanAccessResource", request);
1906
2412
  }
1907
2413
 
1908
2414
  DeleteResource(request) {
1909
- return unaryCall.call(this, "DeleteResource", request);
2415
+ return unaryCallInternal.call(this, "DeleteResource", request);
1910
2416
  }
1911
2417
 
1912
2418
  DiscoverServices(request) {
1913
- return unaryCall.call(this, "DiscoverServices", request);
2419
+ return unaryCallInternal.call(this, "DiscoverServices", request);
1914
2420
  }
1915
2421
 
1916
2422
  GetResource(request) {
1917
- return unaryCall.call(this, "GetResource", request);
2423
+ return unaryCallInternal.call(this, "GetResource", request);
1918
2424
  }
1919
2425
 
1920
2426
  GetResources(request) {
1921
- return unaryCall.call(this, "GetResources", request);
2427
+ return unaryCallInternal.call(this, "GetResources", request);
1922
2428
  }
1923
2429
 
1924
2430
  GetResourceAncestors(request) {
1925
- return unaryCall.call(this, "GetResourceAncestors", request);
2431
+ return unaryCallInternal.call(this, "GetResourceAncestors", request);
1926
2432
  }
1927
2433
 
1928
2434
  GetResourceDescendants(request) {
1929
- return unaryCall.call(this, "GetResourceDescendants", request);
2435
+ return unaryCallInternal.call(this, "GetResourceDescendants", request);
1930
2436
  }
1931
2437
 
1932
2438
  RequestAccess(request) {
1933
- return unaryCall.call(this, "RequestAccess", request);
2439
+ return unaryCallInternal.call(this, "RequestAccess", request);
1934
2440
  }
1935
2441
 
1936
2442
  SaveResource(request) {
1937
- return unaryCall.call(this, "SaveResource", request);
2443
+ return unaryCallInternal.call(this, "SaveResource", request);
1938
2444
  }
1939
2445
 
1940
2446
  SaveResourceAttribute(request) {
1941
- return unaryCall.call(this, "SaveResourceAttribute", request);
2447
+ return unaryCallInternal.call(this, "SaveResourceAttribute", request);
1942
2448
  }
1943
2449
 
1944
2450
  SetServiceStatus(request) {
1945
- return unaryCall.call(this, "SetServiceStatus", request);
2451
+ return unaryCallInternal.call(this, "SetServiceStatus", request);
1946
2452
  }
1947
2453
 
1948
2454
  /**
@@ -1950,82 +2456,82 @@ class VoltClient extends EventEmitter__default["default"] {
1950
2456
  */
1951
2457
 
1952
2458
  Bind(request) {
1953
- return unaryCall.call(this, "Bind", request);
2459
+ return unaryCallInternal.call(this, "Bind", request);
1954
2460
  }
1955
2461
 
1956
2462
  DeleteAccess(request) {
1957
- return unaryCall.call(this, "DeleteAccess", request);
2463
+ return unaryCallInternal.call(this, "DeleteAccess", request);
1958
2464
  }
1959
2465
 
1960
2466
  DeleteVolt(request) {
1961
- return unaryCall.call(this, "DeleteVolt", request);
2467
+ return unaryCallInternal.call(this, "DeleteVolt", request);
1962
2468
  }
1963
2469
 
1964
2470
  GetAccess(request) {
1965
- return unaryCall.call(this, "GetAccess", request);
2471
+ return unaryCallInternal.call(this, "GetAccess", request);
1966
2472
  }
1967
2473
 
1968
2474
  GetBindings(request) {
1969
- return unaryCall.call(this, "GetBindings", request);
2475
+ return unaryCallInternal.call(this, "GetBindings", request);
1970
2476
  }
1971
2477
 
1972
2478
  GetIdentities(request) {
1973
- return unaryCall.call(this, "GetIdentities", request);
2479
+ return unaryCallInternal.call(this, "GetIdentities", request);
1974
2480
  }
1975
2481
 
1976
2482
  GetIdentity(request) {
1977
- return unaryCall.call(this, "GetIdentity", request);
2483
+ return unaryCallInternal.call(this, "GetIdentity", request);
1978
2484
  }
1979
2485
 
1980
2486
  GetIdentityToken(request) {
1981
- return unaryCall.call(this, "GetIdentityToken", request);
2487
+ return unaryCallInternal.call(this, "GetIdentityToken", request);
1982
2488
  }
1983
2489
 
1984
2490
  GetPolicy(request) {
1985
- return unaryCall.call(this, "GetPolicy", request);
2491
+ return unaryCallInternal.call(this, "GetPolicy", request);
1986
2492
  }
1987
2493
 
1988
2494
  GetSettings(request) {
1989
- return unaryCall.call(this, "GetSettings", request);
2495
+ return unaryCallInternal.call(this, "GetSettings", request);
1990
2496
  }
1991
2497
 
1992
2498
  SaveAccess(request) {
1993
- return unaryCall.call(this, "SaveAccess", request);
2499
+ return unaryCallInternal.call(this, "SaveAccess", request);
1994
2500
  }
1995
2501
 
1996
2502
  SaveCloudConnection(request) {
1997
- return unaryCall.call(this, "SaveCloudConnection", request);
2503
+ return unaryCallInternal.call(this, "SaveCloudConnection", request);
1998
2504
  }
1999
2505
 
2000
2506
  SaveIdentity(request) {
2001
- return unaryCall.call(this, "SaveIdentity", request);
2507
+ return unaryCallInternal.call(this, "SaveIdentity", request);
2002
2508
  }
2003
2509
 
2004
2510
  SaveSettings(request) {
2005
- return unaryCall.call(this, "SaveSettings", request);
2511
+ return unaryCallInternal.call(this, "SaveSettings", request);
2006
2512
  }
2007
2513
 
2008
2514
  SetAccessRequestDecision(request) {
2009
- return unaryCall.call(this, "SetAccessRequestDecision", request);
2515
+ return unaryCallInternal.call(this, "SetAccessRequestDecision", request);
2010
2516
  }
2011
2517
 
2012
2518
  SetBindingDecision(request) {
2013
- return unaryCall.call(this, "SetBindingDecision", request);
2519
+ return unaryCallInternal.call(this, "SetBindingDecision", request);
2014
2520
  }
2015
2521
 
2016
2522
  Shutdown(request) {
2017
- return unaryCall.call(this, "Shutdown", request);
2523
+ return unaryCallInternal.call(this, "Shutdown", request);
2018
2524
  }
2019
2525
 
2020
2526
  SignVerify(request) {
2021
- return unaryCall.call(this, "SignVerify", request);
2527
+ return unaryCallInternal.call(this, "SignVerify", request);
2022
2528
  }
2023
2529
 
2024
2530
  /**
2025
2531
  * FileAPI
2026
2532
  */
2027
2533
  GetFileDescendants(request) {
2028
- return unaryCall.call(this, "GetFileDescendants", request);
2534
+ return unaryCallInternal.call(this, "GetFileDescendants", request);
2029
2535
  }
2030
2536
 
2031
2537
  /**
@@ -2103,6 +2609,10 @@ class VoltClient extends EventEmitter__default["default"] {
2103
2609
  /**
2104
2610
  * SqliteDatabaseAPI
2105
2611
  */
2612
+ BulkUpdate(request) {
2613
+ return unaryCallInternal.call(this, "BulkUpdate", request);
2614
+ }
2615
+
2106
2616
  SqlExecute(request) {
2107
2617
  const grpcClient = this.getVoltAPIClient();
2108
2618