@tdxvolt/volt-client-grpc 0.14.61 → 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
 
@@ -527,6 +527,10 @@ class VoltCredential {
527
527
  return this._cryptoCache.client_id;
528
528
  }
529
529
 
530
+ get voltPublicKey() {
531
+ return this._voltPublicKey;
532
+ }
533
+
530
534
  get publicKey() {
531
535
  return pki$1.publicKeyToPem(this.getKey().publicKey);
532
536
  }
@@ -547,17 +551,17 @@ class VoltCredential {
547
551
  createKey() {
548
552
  if (this._cryptoCache.key) {
549
553
  // Already have key data in the cache in pem format => create fully-formed pki instances.
550
- log$4("createKey - key already exists");
554
+ log$5("createKey - key already exists");
551
555
  return Promise.resolve(this.getKey());
552
556
  } else {
553
- log$4("creating key");
557
+ log$5("creating key");
554
558
  return new Promise((resolve, reject) => {
555
559
  pki$1.rsa.generateKeyPair({ bits: 2048, workers: -1 }, (err, keypair) => {
556
560
  if (err) {
557
- log$4("failure creating key [%s]", err.message);
561
+ log$5("failure creating key [%s]", err.message);
558
562
  reject(err);
559
563
  } else {
560
- log$4("successfully created key");
564
+ log$5("successfully created key");
561
565
  const pem = pki$1.privateKeyToPem(keypair.privateKey);
562
566
  this._cryptoCache.key = pem;
563
567
  resolve(keypair);
@@ -579,7 +583,7 @@ class VoltCredential {
579
583
  return this._cryptoCache;
580
584
  })
581
585
  .catch((err) => {
582
- log$4("failure initialising crypto [%s]", err.message);
586
+ log$5("failure initialising crypto [%s]", err.message);
583
587
  return Promise.reject(err);
584
588
  });
585
589
  }
@@ -594,7 +598,7 @@ class VoltCredential {
594
598
  * @param {*} tunnelling flag indicating if the token is required for a tunnelled connection
595
599
  * @param {*} ttl time to live in seconds (default to 1 minute)
596
600
  */
597
- getIdentityToken(audience, tunnelling = false, ttl = 60) {
601
+ getIdentityToken(audience, publicKey, tunnelling = false, ttl = 60) {
598
602
  if (!this._cryptoCache.key) {
599
603
  throw new Error("crypto cache invalid");
600
604
  }
@@ -603,7 +607,7 @@ class VoltCredential {
603
607
  const publicKeyPem = pki$1.publicKeyToPem(keyPair.publicKey);
604
608
  const base58Key = createPublicKeyFingerprint(publicKeyPem);
605
609
 
606
- log$4("base58 key is %s", base58Key);
610
+ log$5("base58 key is %s", base58Key);
607
611
 
608
612
  // Allow TTL either side of the current time.
609
613
  // @todo - fix with server time sync on volt connection.
@@ -620,11 +624,8 @@ class VoltCredential {
620
624
  sharedKey = VoltCredential.aesCreateKey();
621
625
 
622
626
  // Encrypt the key details using the target Volt public key and include this in the JWT payload.
623
- payload.sk = VoltCredential.rsaEncrypt(
624
- this._voltPublicKey,
625
- sharedKey.key,
626
- );
627
- payload.iv = VoltCredential.rsaEncrypt(this._voltPublicKey, sharedKey.iv);
627
+ payload.sk = VoltCredential.rsaEncrypt(publicKey, sharedKey.key);
628
+ payload.iv = VoltCredential.rsaEncrypt(publicKey, sharedKey.iv);
628
629
  }
629
630
 
630
631
  // Sign synchronously.
@@ -649,9 +650,10 @@ class VoltCredential {
649
650
  * @param {*} ttl
650
651
  * @returns
651
652
  */
652
- getIdentityMetadata(grpc, audience, tunnelling = false, ttl = 60) {
653
+ getIdentityMetadata(grpc, audience, publicKey, tunnelling = false, ttl = 60) {
653
654
  const identityToken = this.getIdentityToken(
654
655
  audience || this._voltConfig.id,
656
+ publicKey,
655
657
  tunnelling,
656
658
  ttl,
657
659
  );
@@ -697,6 +699,12 @@ class VoltCredential {
697
699
  static rsaEncrypt(key, buffer) {
698
700
  return crypto__default["default"].publicEncrypt(key, buffer).toString("base64");
699
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
+ }
700
708
  }
701
709
 
702
710
  const { get: getProp, snakeCase } = lodash__default["default"];
@@ -713,23 +721,23 @@ const defaultLoaderOptions = {
713
721
  includeDirs: [defaultProtoPath],
714
722
  };
715
723
 
716
- const getProtoDescriptors = (grpc, protoPath, opts) => {
724
+ function getProtoDescriptors(grpc, protoPath, opts) {
717
725
  const definition = protoLoader__default["default"].loadSync(
718
726
  protoPath,
719
727
  opts || defaultLoaderOptions,
720
728
  );
721
729
  const descriptors = grpc.loadPackageDefinition(definition);
722
730
  return descriptors;
723
- };
731
+ }
724
732
 
725
- const getProtoService = (descriptors, servicePath) => {
733
+ function getProtoService(descriptors, servicePath) {
726
734
  const serviceDef = getProp(descriptors, servicePath);
727
735
  if (serviceDef?.service) {
728
736
  return serviceDef.service;
729
737
  } else {
730
738
  return null;
731
739
  }
732
- };
740
+ }
733
741
 
734
742
  function getServiceDescriptorsFromPath(
735
743
  grpc,
@@ -737,8 +745,30 @@ function getServiceDescriptorsFromPath(
737
745
  servicePackageName,
738
746
  opts,
739
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
+
740
770
  let serviceDescriptors;
741
- const descriptors = getProtoDescriptors(grpc, protoPath, opts);
771
+ const descriptors = getProtoDescriptors(grpc, serviceProtoPath, opts);
742
772
  if (descriptors) {
743
773
  serviceDescriptors = getProtoService(descriptors, servicePackageName);
744
774
  }
@@ -786,8 +816,17 @@ function getProtoDescriptorMethods(protoDescriptor) {
786
816
  return methods;
787
817
  }
788
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
+
789
827
  var protoUtils = /*#__PURE__*/Object.freeze({
790
828
  __proto__: null,
829
+ createServiceProtobufFiles: createServiceProtobufFiles,
791
830
  getServiceDescriptors: getServiceDescriptors,
792
831
  getProtoDescriptors: getProtoDescriptors,
793
832
  getProtoDescriptorMethods: getProtoDescriptorMethods,
@@ -796,70 +835,101 @@ var protoUtils = /*#__PURE__*/Object.freeze({
796
835
 
797
836
  /* eslint-disable no-underscore-dangle */
798
837
 
799
- const log$3 = debug__default["default"]("volt-client-grpc:grpc-call");
838
+ const log$4 = debug__default["default"]("volt-client-grpc:grpc-call");
800
839
 
801
840
  function _prepareInvokeRequest(
802
841
  request,
803
842
  method,
804
843
  methodType = "METHOD_TYPE_UNARY",
805
844
  ) {
806
- 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(
807
851
  this._voltClient.grpc,
808
- this._voltClient.voltConfig.id,
809
- 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,
810
857
  );
858
+
811
859
  let invokeRequest;
812
860
  let callMethod = method;
813
861
 
814
- 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
+ //
815
867
  let requestPayload;
868
+
869
+ // Serialise the rpc request.
816
870
  if (request) {
817
871
  requestPayload = this._grpcClient[method].requestSerialize(request);
818
872
  } else if (request !== null) {
819
- log$3("****************LOOKOUT****************** - empty request");
873
+ log$4("****************LOOKOUT****************** - empty request");
820
874
  } else {
821
- log$3("explicit empty request payload");
875
+ log$4("explicit empty request payload");
822
876
  }
823
877
 
824
- 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;
825
881
 
826
882
  const tunnelResp = {
827
883
  method_invoke: {
828
884
  method_name: this._grpcClient[method].path,
829
885
  method_type: methodType,
830
- token: meta.token,
886
+ token: methodToken.token,
831
887
  request: requestPayload,
832
888
  },
833
889
  };
834
890
 
835
- const invokePayload = VoltCredential.aesEncrypt(
836
- tunnelMethod.responseSerialize(tunnelResp),
837
- meta.sharedKey.key,
838
- meta.sharedKey.iv,
839
- );
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
+ }
840
903
 
841
- log$3("target volt is %s", this._voltClient.credential.voltFingerprint);
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
+ }
915
+
916
+ log$4("target is %j", targetFingerprint);
842
917
 
843
918
  invokeRequest = {
844
- identity_fingerprint: this._voltClient.credential.voltFingerprint,
919
+ target_fingerprint: targetFingerprint,
920
+ token: methodToken.token,
845
921
  payload: invokePayload,
922
+ target_service_id: isServiceRelayed ? this._service.id : undefined,
846
923
  };
847
924
 
925
+ // Replace the target method with a call to Invoke on the relay Volt.
848
926
  callMethod = "Invoke";
849
- } else if (this._voltClient.isRemote && meta.sharedKey.key) {
850
- const requestPayload =
851
- this._grpcClient[method].requestSerializeOriginal(request);
852
- invokeRequest = VoltCredential.aesEncrypt(
853
- requestPayload,
854
- meta.sharedKey.key,
855
- meta.sharedKey.iv,
856
- );
857
927
  } else {
858
928
  invokeRequest = request;
859
929
  }
860
930
 
861
931
  return {
862
- meta,
932
+ meta: methodToken,
863
933
  method: callMethod,
864
934
  methodName: method,
865
935
  request: invokeRequest,
@@ -869,10 +939,16 @@ function _prepareInvokeRequest(
869
939
  function _preparePayloadRequest(request, invokeInfo) {
870
940
  let payloadRequest;
871
941
 
872
- 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) {
873
947
  const requestPayload =
874
948
  this._grpcClient[invokeInfo.methodName].requestSerialize(request);
875
- const tunnelMethod = this._grpcClient.Tunnel;
949
+
950
+ const voltGrpcClient = this._voltClient.getVoltAPIClient();
951
+ const tunnelMethod = voltGrpcClient.Tunnel;
876
952
 
877
953
  const tunnelResp = {
878
954
  method_payload: {
@@ -889,14 +965,6 @@ function _preparePayloadRequest(request, invokeInfo) {
889
965
  payloadRequest = {
890
966
  payload: invokePayload,
891
967
  };
892
- } else if (this._voltClient.isRemote && invokeInfo.meta.sharedKey.key) {
893
- const requestPayload =
894
- this._grpcClient[invokeInfo.methodName].requestSerializeOriginal(request);
895
- payloadRequest = VoltCredential.aesEncrypt(
896
- requestPayload,
897
- invokeInfo.meta.sharedKey.key,
898
- invokeInfo.meta.sharedKey.iv,
899
- );
900
968
  } else {
901
969
  payloadRequest = request;
902
970
  }
@@ -905,29 +973,47 @@ function _preparePayloadRequest(request, invokeInfo) {
905
973
  }
906
974
 
907
975
  function _parseResponse(method, meta, response) {
976
+ // log("parseResponse for %s", this._methodName);
908
977
  let invokeResponse = {};
909
978
 
910
- 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) {
911
984
  if (response.payload) {
912
- const decryptedPayload = VoltCredential.aesDecrypt(
913
- response.payload,
914
- meta.sharedKey.key,
915
- meta.sharedKey.iv,
916
- );
917
- 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;
918
997
  const responsePayload = tunnelMethod.requestDeserialize(decryptedPayload);
919
998
  if (responsePayload.payload === "method_payload") {
920
- invokeResponse.payload = this._grpcClient[method].responseDeserialize(
921
- responsePayload.method_payload.payload,
922
- );
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
+ }
923
1009
  } else if (responsePayload.payload === "method_end") {
924
1010
  invokeResponse = responsePayload.method_end;
925
1011
  } else {
926
- log$3("unexpected tunnel payload type: %s", responsePayload.payload);
1012
+ log$4("unexpected tunnel payload type: %s", responsePayload.payload);
927
1013
  }
928
1014
  } else if (response.status?.message) {
929
1015
  // There's been an error in the tunnel.
930
- log$3(
1016
+ log$4(
931
1017
  "Tunnel status received: %s, code %d, description: %s",
932
1018
  response.status.message,
933
1019
  response.status.code,
@@ -939,7 +1025,7 @@ function _parseResponse(method, meta, response) {
939
1025
  };
940
1026
  } else {
941
1027
  invokeResponse.methodId = response.invoke_id;
942
- log$3("started method %d for %s", invokeResponse.methodId, method);
1028
+ log$4("started method %d for %s", invokeResponse.methodId, method);
943
1029
  }
944
1030
  } else if (this._voltClient.isRemote && meta.sharedKey.key) {
945
1031
  const decryptedPayload = VoltCredential.aesDecrypt(
@@ -959,17 +1045,22 @@ function _parseResponse(method, meta, response) {
959
1045
  }
960
1046
 
961
1047
  class GRPCCall extends EventEmitter__default["default"] {
962
- constructor(voltClient, methodName, methodType) {
1048
+ constructor(voltClient, methodName, methodType, service = undefined) {
963
1049
  super();
964
1050
  this._methodName = methodName;
965
1051
  this._methodType = methodType;
966
1052
  this._call = null;
967
1053
  this._voltClient = voltClient;
1054
+ this._service = service;
968
1055
  }
969
1056
 
970
1057
  start(grpcClient, request) {
971
1058
  this._grpcClient = grpcClient;
972
1059
 
1060
+ if (typeof this._grpcClient[this._methodName] !== "function") {
1061
+ throw new Error(`method not found: '${this._methodName}'`);
1062
+ }
1063
+
973
1064
  this._initialRequest = _prepareInvokeRequest.call(
974
1065
  this,
975
1066
  request,
@@ -977,13 +1068,18 @@ class GRPCCall extends EventEmitter__default["default"] {
977
1068
  this._methodType,
978
1069
  );
979
1070
 
980
- if (!this._grpcClient[this._initialRequest.method]) {
981
- return reject(
982
- new Error(`method not found: '${this._initialRequest.method}'`),
983
- );
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;
984
1080
  }
985
1081
 
986
- this._call = this._grpcClient[this._initialRequest.method](
1082
+ this._call = callClient[this._initialRequest.method](
987
1083
  this._initialRequest.meta.metadata,
988
1084
  );
989
1085
 
@@ -1013,28 +1109,32 @@ class GRPCCall extends EventEmitter__default["default"] {
1013
1109
  this.emit("end");
1014
1110
  }
1015
1111
  } else {
1016
- log$3("method id is %s", parsedResponse.methodId);
1112
+ log$4("method id is %s", parsedResponse.methodId);
1017
1113
  }
1018
1114
  } catch (err) {
1019
- 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
+ );
1020
1120
  this.emit("error", err);
1021
1121
  }
1022
1122
  });
1023
1123
 
1024
1124
  this._call.on("error", (err) => {
1025
- log$3("ERROR - intercepted stream error %s", err.message);
1125
+ log$4("ERROR - intercepted stream error %s", err.message);
1026
1126
  this.emit("error", err);
1027
1127
  });
1028
1128
 
1029
1129
  this._call.on("finish", () => {
1030
1130
  // The read side has ended (i.e. we called end()).
1031
- log$3("finished call %s", this._methodName);
1131
+ log$4("finished call %s", this._methodName);
1032
1132
  this.emit("finish");
1033
1133
  });
1034
1134
 
1035
1135
  this._call.on("end", () => {
1036
1136
  // The remote peer ended the stream.
1037
- log$3(
1137
+ log$4(
1038
1138
  "ended call %s, method id: %s",
1039
1139
  this._methodName,
1040
1140
  this._initialRequest.methodId || "n/a - not tunnelling",
@@ -1064,7 +1164,7 @@ class GRPCCall extends EventEmitter__default["default"] {
1064
1164
 
1065
1165
  write(request) {
1066
1166
  if (!this._call) {
1067
- log$3("ERROR - call not initialised");
1167
+ log$4("ERROR - call not initialised");
1068
1168
  throw new Error("call not initialised");
1069
1169
  } else if (this._initialRequest) {
1070
1170
  const payloadRequest = _preparePayloadRequest.call(
@@ -1088,7 +1188,7 @@ class GRPCCall extends EventEmitter__default["default"] {
1088
1188
 
1089
1189
  /* eslint-disable no-use-before-define */
1090
1190
 
1091
- const log$2 = debug__default["default"]("volt-client-grpc:volt-connection");
1191
+ const log$3 = debug__default["default"]("volt-client-grpc:volt-connection");
1092
1192
 
1093
1193
  function _cleanUp(immediateReconnect) {
1094
1194
  this._connectionId = "";
@@ -1122,7 +1222,7 @@ function _cleanUp(immediateReconnect) {
1122
1222
  }
1123
1223
 
1124
1224
  function _connectionTimeoutHandler() {
1125
- log$2("server timed out");
1225
+ log$3("server timed out");
1126
1226
  this.emit("connected", false);
1127
1227
  _cleanUp.call(this);
1128
1228
  }
@@ -1134,14 +1234,14 @@ function _doConnect(connectHello) {
1134
1234
 
1135
1235
  let helloPayload = connectHello;
1136
1236
  if (!connectHello) {
1137
- log$2("defaulting hello payload");
1237
+ log$3("defaulting hello payload");
1138
1238
  helloPayload = {
1139
1239
  hello: {},
1140
1240
  };
1141
1241
  }
1142
1242
 
1143
1243
  this.call.on("error", (err) => {
1144
- log$2("error on connection stream [%s]", err.message);
1244
+ log$3("error on connection stream [%s]", err.message);
1145
1245
  _cleanUp.call(this);
1146
1246
  this.emit("error", err);
1147
1247
  });
@@ -1149,7 +1249,7 @@ function _doConnect(connectHello) {
1149
1249
  this.call.on("data", (response) => {
1150
1250
  switch (response.payload) {
1151
1251
  case "ping": {
1152
- log$2("pinged");
1252
+ log$3("pinged");
1153
1253
 
1154
1254
  // Received ping response from server => clear timeout.
1155
1255
  if (this._pingTimeoutTimer) {
@@ -1163,18 +1263,23 @@ function _doConnect(connectHello) {
1163
1263
  case "acknowledge": {
1164
1264
  if (!this._connectionId) {
1165
1265
  this._connectionId = response.acknowledge.connection_id;
1166
- log$2("connection id is %s", this._connectionId);
1266
+ log$3("connection id is %s", this._connectionId);
1167
1267
  this.emit("connected", this._connectionId);
1168
1268
  }
1169
1269
  break;
1170
1270
  }
1271
+ case "invoke_request": {
1272
+ log$3("received invoke request");
1273
+ this.emit("invoke_request", response.invoke_request);
1274
+ break;
1275
+ }
1171
1276
  case "evt": {
1172
- log$2("received event %s", response.evt.event_type);
1277
+ log$3("received event %s", response.evt.event_type);
1173
1278
  this.emit("evt", response.evt);
1174
1279
  break;
1175
1280
  }
1176
1281
  default:
1177
- log$2("unimplemented connect response payload: %s", response.payload);
1282
+ log$3("unimplemented connect response payload: %s", response.payload);
1178
1283
  break;
1179
1284
  }
1180
1285
  });
@@ -1193,7 +1298,7 @@ function _doConnect(connectHello) {
1193
1298
 
1194
1299
  function _startPingTimer() {
1195
1300
  if (this._pingTimer) {
1196
- log$2("ping timer running");
1301
+ log$3("ping timer running");
1197
1302
  return;
1198
1303
  }
1199
1304
 
@@ -1201,7 +1306,7 @@ function _startPingTimer() {
1201
1306
  // Send next ping to server.
1202
1307
  const request = { ping: { timestamp: Date.now() } };
1203
1308
 
1204
- log$2("pinging Volt");
1309
+ log$3("pinging Volt");
1205
1310
  this.call.write(request);
1206
1311
 
1207
1312
  this._pingTimer = 0;
@@ -1250,6 +1355,277 @@ class VoltConnection extends EventEmitter__default["default"] {
1250
1355
  this._dying = true;
1251
1356
  _cleanUp.call(this);
1252
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
+ }
1253
1629
  }
1254
1630
 
1255
1631
  /* eslint-disable no-underscore-dangle */
@@ -1270,46 +1646,48 @@ const voltServices = [
1270
1646
 
1271
1647
  function issueBind(bindRequest, ttl) {
1272
1648
  // eslint-disable-next-line no-use-before-define
1273
- return unaryCall.call(this, "Bind", bindRequest).then((bindResponse) => {
1274
- log$1("got binding request response %j", bindResponse);
1275
- if (bindResponse.status?.code) {
1276
- log$1("error in bind response: %s", bindResponse.status.message);
1277
- return Promise.reject(new Error(bindResponse.status.message));
1278
- } else {
1279
- switch (bindResponse.decision) {
1280
- case "POLICY_DECISION_PERMIT": {
1281
- //
1282
- // The request status is permit => cache the bind response info.
1283
- //
1284
-
1285
- // This is the certificate assigned to us by the volt.
1286
- this._credential.cache.cert = bindResponse.cert;
1287
-
1288
- // This is the signing CA used by the volt.
1289
- this._credential.cache.ca = bindResponse.chain;
1290
-
1291
- // Identity resource id is assigned by the volt.
1292
- this._credential.cache.client_id = bindResponse.identity_id;
1293
- this._credential.saveCache();
1294
- break;
1295
- }
1296
- case "POLICY_DECISION_DENY": {
1297
- log$1(">>>>>>>>>>>>>>> access request is DENIED <<<<<<<<<<<<<<<<<<<");
1298
- break;
1299
- }
1300
- case "POLICY_DECISION_PROMPT":
1301
- case "POLICY_DECISION_PENDING": {
1302
- log$1("access pending approval - waiting...");
1303
- 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;
1304
1686
  }
1305
- default:
1306
- log$1("ignoring unknown bind descision %s", bindResponse.status);
1307
- break;
1308
1687
  }
1309
- }
1310
1688
 
1311
- return bindResponse.decision;
1312
- });
1689
+ return bindResponse.decision;
1690
+ });
1313
1691
  }
1314
1692
 
1315
1693
  function findDIDDocumentService(document, serviceType) {
@@ -1476,6 +1854,30 @@ function connectInternal(helloPayload) {
1476
1854
  this.emit("evt", evt);
1477
1855
  });
1478
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
+
1479
1881
  return this._voltConnection.connect(helloPayload);
1480
1882
  } catch (err) {
1481
1883
  log$1("connect - error [%s]", err.message);
@@ -1509,11 +1911,61 @@ function getVoltAPIClientInternal() {
1509
1911
  return this._cachedClient;
1510
1912
  }
1511
1913
 
1512
- function unaryCall(method, request) {
1513
- return new Promise((resolve, reject) => {
1514
- 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
+ }
1515
1935
 
1516
- const call = new GRPCCall(this, method, "METHOD_TYPE_UNARY");
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
+ }
1960
+
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);
1517
1969
 
1518
1970
  let response = null;
1519
1971
 
@@ -1541,6 +1993,16 @@ function unaryCall(method, request) {
1541
1993
  });
1542
1994
  }
1543
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
+
1544
2006
  async function fetchVoltConfig(discovery_url) {
1545
2007
  try {
1546
2008
  const getJSON = bent__default["default"]("json");
@@ -1621,6 +2083,8 @@ class VoltClient extends EventEmitter__default["default"] {
1621
2083
  this._config = null;
1622
2084
  this._voltConfig = null;
1623
2085
  this._voltConnection = null;
2086
+ this._cachedService = {};
2087
+ this._activeRPC = {};
1624
2088
  }
1625
2089
 
1626
2090
  get config() {
@@ -1866,6 +2330,40 @@ class VoltClient extends EventEmitter__default["default"] {
1866
2330
  return getVoltAPIClientInternal.call(this);
1867
2331
  }
1868
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
+
1869
2367
  /**
1870
2368
  * Request resource access.
1871
2369
  * @param {*} targetResourceId
@@ -1910,47 +2408,47 @@ class VoltClient extends EventEmitter__default["default"] {
1910
2408
  */
1911
2409
 
1912
2410
  CanAccessResource(request) {
1913
- return unaryCall.call(this, "CanAccessResource", request);
2411
+ return unaryCallInternal.call(this, "CanAccessResource", request);
1914
2412
  }
1915
2413
 
1916
2414
  DeleteResource(request) {
1917
- return unaryCall.call(this, "DeleteResource", request);
2415
+ return unaryCallInternal.call(this, "DeleteResource", request);
1918
2416
  }
1919
2417
 
1920
2418
  DiscoverServices(request) {
1921
- return unaryCall.call(this, "DiscoverServices", request);
2419
+ return unaryCallInternal.call(this, "DiscoverServices", request);
1922
2420
  }
1923
2421
 
1924
2422
  GetResource(request) {
1925
- return unaryCall.call(this, "GetResource", request);
2423
+ return unaryCallInternal.call(this, "GetResource", request);
1926
2424
  }
1927
2425
 
1928
2426
  GetResources(request) {
1929
- return unaryCall.call(this, "GetResources", request);
2427
+ return unaryCallInternal.call(this, "GetResources", request);
1930
2428
  }
1931
2429
 
1932
2430
  GetResourceAncestors(request) {
1933
- return unaryCall.call(this, "GetResourceAncestors", request);
2431
+ return unaryCallInternal.call(this, "GetResourceAncestors", request);
1934
2432
  }
1935
2433
 
1936
2434
  GetResourceDescendants(request) {
1937
- return unaryCall.call(this, "GetResourceDescendants", request);
2435
+ return unaryCallInternal.call(this, "GetResourceDescendants", request);
1938
2436
  }
1939
2437
 
1940
2438
  RequestAccess(request) {
1941
- return unaryCall.call(this, "RequestAccess", request);
2439
+ return unaryCallInternal.call(this, "RequestAccess", request);
1942
2440
  }
1943
2441
 
1944
2442
  SaveResource(request) {
1945
- return unaryCall.call(this, "SaveResource", request);
2443
+ return unaryCallInternal.call(this, "SaveResource", request);
1946
2444
  }
1947
2445
 
1948
2446
  SaveResourceAttribute(request) {
1949
- return unaryCall.call(this, "SaveResourceAttribute", request);
2447
+ return unaryCallInternal.call(this, "SaveResourceAttribute", request);
1950
2448
  }
1951
2449
 
1952
2450
  SetServiceStatus(request) {
1953
- return unaryCall.call(this, "SetServiceStatus", request);
2451
+ return unaryCallInternal.call(this, "SetServiceStatus", request);
1954
2452
  }
1955
2453
 
1956
2454
  /**
@@ -1958,82 +2456,82 @@ class VoltClient extends EventEmitter__default["default"] {
1958
2456
  */
1959
2457
 
1960
2458
  Bind(request) {
1961
- return unaryCall.call(this, "Bind", request);
2459
+ return unaryCallInternal.call(this, "Bind", request);
1962
2460
  }
1963
2461
 
1964
2462
  DeleteAccess(request) {
1965
- return unaryCall.call(this, "DeleteAccess", request);
2463
+ return unaryCallInternal.call(this, "DeleteAccess", request);
1966
2464
  }
1967
2465
 
1968
2466
  DeleteVolt(request) {
1969
- return unaryCall.call(this, "DeleteVolt", request);
2467
+ return unaryCallInternal.call(this, "DeleteVolt", request);
1970
2468
  }
1971
2469
 
1972
2470
  GetAccess(request) {
1973
- return unaryCall.call(this, "GetAccess", request);
2471
+ return unaryCallInternal.call(this, "GetAccess", request);
1974
2472
  }
1975
2473
 
1976
2474
  GetBindings(request) {
1977
- return unaryCall.call(this, "GetBindings", request);
2475
+ return unaryCallInternal.call(this, "GetBindings", request);
1978
2476
  }
1979
2477
 
1980
2478
  GetIdentities(request) {
1981
- return unaryCall.call(this, "GetIdentities", request);
2479
+ return unaryCallInternal.call(this, "GetIdentities", request);
1982
2480
  }
1983
2481
 
1984
2482
  GetIdentity(request) {
1985
- return unaryCall.call(this, "GetIdentity", request);
2483
+ return unaryCallInternal.call(this, "GetIdentity", request);
1986
2484
  }
1987
2485
 
1988
2486
  GetIdentityToken(request) {
1989
- return unaryCall.call(this, "GetIdentityToken", request);
2487
+ return unaryCallInternal.call(this, "GetIdentityToken", request);
1990
2488
  }
1991
2489
 
1992
2490
  GetPolicy(request) {
1993
- return unaryCall.call(this, "GetPolicy", request);
2491
+ return unaryCallInternal.call(this, "GetPolicy", request);
1994
2492
  }
1995
2493
 
1996
2494
  GetSettings(request) {
1997
- return unaryCall.call(this, "GetSettings", request);
2495
+ return unaryCallInternal.call(this, "GetSettings", request);
1998
2496
  }
1999
2497
 
2000
2498
  SaveAccess(request) {
2001
- return unaryCall.call(this, "SaveAccess", request);
2499
+ return unaryCallInternal.call(this, "SaveAccess", request);
2002
2500
  }
2003
2501
 
2004
2502
  SaveCloudConnection(request) {
2005
- return unaryCall.call(this, "SaveCloudConnection", request);
2503
+ return unaryCallInternal.call(this, "SaveCloudConnection", request);
2006
2504
  }
2007
2505
 
2008
2506
  SaveIdentity(request) {
2009
- return unaryCall.call(this, "SaveIdentity", request);
2507
+ return unaryCallInternal.call(this, "SaveIdentity", request);
2010
2508
  }
2011
2509
 
2012
2510
  SaveSettings(request) {
2013
- return unaryCall.call(this, "SaveSettings", request);
2511
+ return unaryCallInternal.call(this, "SaveSettings", request);
2014
2512
  }
2015
2513
 
2016
2514
  SetAccessRequestDecision(request) {
2017
- return unaryCall.call(this, "SetAccessRequestDecision", request);
2515
+ return unaryCallInternal.call(this, "SetAccessRequestDecision", request);
2018
2516
  }
2019
2517
 
2020
2518
  SetBindingDecision(request) {
2021
- return unaryCall.call(this, "SetBindingDecision", request);
2519
+ return unaryCallInternal.call(this, "SetBindingDecision", request);
2022
2520
  }
2023
2521
 
2024
2522
  Shutdown(request) {
2025
- return unaryCall.call(this, "Shutdown", request);
2523
+ return unaryCallInternal.call(this, "Shutdown", request);
2026
2524
  }
2027
2525
 
2028
2526
  SignVerify(request) {
2029
- return unaryCall.call(this, "SignVerify", request);
2527
+ return unaryCallInternal.call(this, "SignVerify", request);
2030
2528
  }
2031
2529
 
2032
2530
  /**
2033
2531
  * FileAPI
2034
2532
  */
2035
2533
  GetFileDescendants(request) {
2036
- return unaryCall.call(this, "GetFileDescendants", request);
2534
+ return unaryCallInternal.call(this, "GetFileDescendants", request);
2037
2535
  }
2038
2536
 
2039
2537
  /**
@@ -2111,6 +2609,10 @@ class VoltClient extends EventEmitter__default["default"] {
2111
2609
  /**
2112
2610
  * SqliteDatabaseAPI
2113
2611
  */
2612
+ BulkUpdate(request) {
2613
+ return unaryCallInternal.call(this, "BulkUpdate", request);
2614
+ }
2615
+
2114
2616
  SqlExecute(request) {
2115
2617
  const grpcClient = this.getVoltAPIClient();
2116
2618