@firebase/data-connect 0.0.2-dataconnect-preview.877f8b7d0 → 0.0.3-dataconnect-preview.d986d4bf2

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.
Files changed (40) hide show
  1. package/dist/index.cjs.js +204 -29
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.esm2017.js +203 -30
  4. package/dist/index.esm2017.js.map +1 -1
  5. package/dist/index.esm5.js +204 -25
  6. package/dist/index.esm5.js.map +1 -1
  7. package/dist/index.node.cjs.js +205 -24
  8. package/dist/index.node.cjs.js.map +1 -1
  9. package/dist/internal.d.ts +159 -13
  10. package/dist/node-esm/index.node.esm.js +203 -30
  11. package/dist/node-esm/index.node.esm.js.map +1 -1
  12. package/dist/node-esm/src/api/DataConnect.d.ts +42 -0
  13. package/dist/node-esm/src/api/Mutation.d.ts +26 -1
  14. package/dist/node-esm/src/api/Reference.d.ts +6 -0
  15. package/dist/node-esm/src/api/index.d.ts +1 -0
  16. package/dist/node-esm/src/api/query.d.ts +51 -1
  17. package/dist/node-esm/src/api.browser.d.ts +12 -7
  18. package/dist/node-esm/src/core/FirebaseAuthProvider.d.ts +1 -1
  19. package/dist/node-esm/src/core/QueryManager.d.ts +1 -1
  20. package/dist/node-esm/src/core/error.d.ts +2 -1
  21. package/dist/node-esm/src/network/fetch.d.ts +1 -1
  22. package/dist/node-esm/src/network/transport/index.d.ts +1 -1
  23. package/dist/node-esm/src/network/transport/rest.d.ts +20 -9
  24. package/dist/node-esm/src/util/validateArgs.d.ts +33 -0
  25. package/dist/private.d.ts +141 -19
  26. package/dist/public.d.ts +130 -15
  27. package/dist/src/api/DataConnect.d.ts +42 -0
  28. package/dist/src/api/Mutation.d.ts +26 -1
  29. package/dist/src/api/Reference.d.ts +6 -0
  30. package/dist/src/api/index.d.ts +1 -0
  31. package/dist/src/api/query.d.ts +51 -1
  32. package/dist/src/api.browser.d.ts +12 -7
  33. package/dist/src/core/FirebaseAuthProvider.d.ts +1 -1
  34. package/dist/src/core/QueryManager.d.ts +1 -1
  35. package/dist/src/core/error.d.ts +2 -1
  36. package/dist/src/network/fetch.d.ts +1 -1
  37. package/dist/src/network/transport/index.d.ts +1 -1
  38. package/dist/src/network/transport/rest.d.ts +20 -9
  39. package/dist/src/util/validateArgs.d.ts +33 -0
  40. package/package.json +10 -6
@@ -30,7 +30,8 @@ var Code = {
30
30
  NOT_INITIALIZED: 'not-initialized',
31
31
  NOT_SUPPORTED: 'not-supported',
32
32
  INVALID_ARGUMENT: 'invalid-argument',
33
- PARTIAL_ERROR: 'partial-error'
33
+ PARTIAL_ERROR: 'partial-error',
34
+ UNAUTHORIZED: 'unauthorized'
34
35
  };
35
36
  /** An error returned by a DataConnect operation. */
36
37
  var DataConnectError = /** @class */ (function (_super) {
@@ -130,14 +131,22 @@ var connectFetch = globalThis.fetch;
130
131
  function initializeFetch(fetchImpl) {
131
132
  connectFetch = fetchImpl;
132
133
  }
133
- function dcFetch(url, body, _a, accessToken) {
134
+ function getGoogApiClientValue(_isUsingGen) {
135
+ var str = 'gl-js/ fire/' + SDK_VERSION;
136
+ if (_isUsingGen) {
137
+ str += ' web/gen';
138
+ }
139
+ return str;
140
+ }
141
+ function dcFetch(url, body, _a, accessToken, _isUsingGen) {
134
142
  var _this = this;
135
143
  var signal = _a.signal;
136
144
  if (!connectFetch) {
137
145
  throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!');
138
146
  }
139
147
  var headers = {
140
- 'Content-Type': 'application/json'
148
+ 'Content-Type': 'application/json',
149
+ 'X-Goog-Api-Client': getGoogApiClientValue(_isUsingGen)
141
150
  };
142
151
  if (accessToken) {
143
152
  headers['X-Firebase-Auth-Token'] = accessToken;
@@ -149,11 +158,12 @@ function dcFetch(url, body, _a, accessToken) {
149
158
  method: 'POST',
150
159
  headers: headers,
151
160
  signal: signal
152
- }).catch(function (err) {
153
- throw new DataConnectError(Code.OTHER, "Failed to fetch: " + JSON.stringify(err));
161
+ })
162
+ .catch(function (err) {
163
+ throw new DataConnectError(Code.OTHER, 'Failed to fetch: ' + JSON.stringify(err));
154
164
  })
155
165
  .then(function (response) { return tslib.__awaiter(_this, void 0, void 0, function () {
156
- var jsonResponse, e_1;
166
+ var jsonResponse, e_1, message;
157
167
  return tslib.__generator(this, function (_a) {
158
168
  switch (_a.label) {
159
169
  case 0:
@@ -169,9 +179,13 @@ function dcFetch(url, body, _a, accessToken) {
169
179
  e_1 = _a.sent();
170
180
  throw new DataConnectError(Code.OTHER, JSON.stringify(e_1));
171
181
  case 4:
182
+ message = getMessage(jsonResponse);
172
183
  if (response.status >= 400) {
173
184
  logError('Error while performing request: ' + JSON.stringify(jsonResponse));
174
- throw new DataConnectError(Code.OTHER, JSON.stringify(jsonResponse));
185
+ if (response.status === 401) {
186
+ throw new DataConnectError(Code.UNAUTHORIZED, message);
187
+ }
188
+ throw new DataConnectError(Code.OTHER, message);
175
189
  }
176
190
  return [2 /*return*/, jsonResponse];
177
191
  }
@@ -185,10 +199,16 @@ function dcFetch(url, body, _a, accessToken) {
185
199
  }
186
200
  return res;
187
201
  });
202
+ }
203
+ function getMessage(obj) {
204
+ if ('message' in obj) {
205
+ return obj.message;
206
+ }
207
+ return JSON.stringify(obj);
188
208
  }
189
209
 
190
210
  var name = "@firebase/data-connect";
191
- var version = "0.0.2-dataconnect-preview.877f8b7d0";
211
+ var version = "0.0.3-dataconnect-preview.d986d4bf2";
192
212
 
193
213
  /**
194
214
  * @license
@@ -250,7 +270,8 @@ var FirebaseAuthProvider = /** @class */ (function () {
250
270
  FirebaseAuthProvider.prototype.removeTokenChangeListener = function (listener) {
251
271
  this._authProvider
252
272
  .get()
253
- .then(function (auth) { return auth.removeAuthTokenListener(listener); });
273
+ .then(function (auth) { return auth.removeAuthTokenListener(listener); })
274
+ .catch(function (err) { return logError(err); });
254
275
  };
255
276
  return FirebaseAuthProvider;
256
277
  }());
@@ -521,11 +542,13 @@ function addToken(url, apiKey) {
521
542
  * limitations under the License.
522
543
  */
523
544
  var RESTTransport = /** @class */ (function () {
524
- function RESTTransport(options, apiKey, authProvider, transportOptions) {
545
+ function RESTTransport(options, apiKey, authProvider, transportOptions, _isUsingGen) {
546
+ if (_isUsingGen === void 0) { _isUsingGen = false; }
525
547
  var _this = this;
526
548
  var _a;
527
549
  this.apiKey = apiKey;
528
550
  this.authProvider = authProvider;
551
+ this._isUsingGen = _isUsingGen;
529
552
  this._host = '';
530
553
  this._location = 'l';
531
554
  this._connectorName = '';
@@ -533,30 +556,32 @@ var RESTTransport = /** @class */ (function () {
533
556
  this._project = 'p';
534
557
  this._accessToken = null;
535
558
  this._authInitialized = false;
559
+ this._lastToken = null;
536
560
  // TODO(mtewani): Update U to include shape of body defined in line 13.
537
561
  this.invokeQuery = function (queryName, body) {
538
562
  var abortController = new AbortController();
539
563
  // TODO(mtewani): Update to proper value
540
- var withAuth = _this.getWithAuth().then(function () {
564
+ var withAuth = _this.withRetry(function () {
541
565
  return dcFetch(addToken("".concat(_this.endpointUrl, ":executeQuery"), _this.apiKey), {
542
566
  name: "projects/".concat(_this._project, "/locations/").concat(_this._location, "/services/").concat(_this._serviceName, "/connectors/").concat(_this._connectorName),
543
567
  operationName: queryName,
544
568
  variables: body
545
569
  }, // TODO(mtewani): This is a patch, fix this.
546
- abortController, _this._accessToken);
570
+ abortController, _this._accessToken, _this._isUsingGen);
547
571
  });
548
572
  return {
549
- then: withAuth.then.bind(withAuth)
573
+ then: withAuth.then.bind(withAuth),
574
+ catch: withAuth.catch.bind(withAuth)
550
575
  };
551
576
  };
552
577
  this.invokeMutation = function (mutationName, body) {
553
578
  var abortController = new AbortController();
554
- var taskResult = _this.getWithAuth().then(function () {
579
+ var taskResult = _this.withRetry(function () {
555
580
  return dcFetch(addToken("".concat(_this.endpointUrl, ":executeMutation"), _this.apiKey), {
556
581
  name: "projects/".concat(_this._project, "/locations/").concat(_this._location, "/services/").concat(_this._serviceName, "/connectors/").concat(_this._connectorName),
557
582
  operationName: mutationName,
558
583
  variables: body
559
- }, abortController, _this._accessToken);
584
+ }, abortController, _this._accessToken, _this._isUsingGen);
560
585
  });
561
586
  return {
562
587
  then: taskResult.then.bind(taskResult),
@@ -615,15 +640,16 @@ var RESTTransport = /** @class */ (function () {
615
640
  RESTTransport.prototype.onTokenChanged = function (newToken) {
616
641
  this._accessToken = newToken;
617
642
  };
618
- RESTTransport.prototype.getWithAuth = function () {
643
+ RESTTransport.prototype.getWithAuth = function (forceToken) {
619
644
  var _this = this;
645
+ if (forceToken === void 0) { forceToken = false; }
620
646
  var starterPromise = new Promise(function (resolve) {
621
647
  return resolve(_this._accessToken);
622
648
  });
623
649
  if (!this._authInitialized) {
624
650
  if (this.authProvider) {
625
651
  starterPromise = this.authProvider
626
- .getToken(/*forceToken=*/ false)
652
+ .getToken(/*forceToken=*/ forceToken)
627
653
  .then(function (data) {
628
654
  if (!data) {
629
655
  return null;
@@ -638,6 +664,32 @@ var RESTTransport = /** @class */ (function () {
638
664
  }
639
665
  return starterPromise;
640
666
  };
667
+ RESTTransport.prototype._setLastToken = function (lastToken) {
668
+ this._lastToken = lastToken;
669
+ };
670
+ RESTTransport.prototype.withRetry = function (promiseFactory, retry) {
671
+ var _this = this;
672
+ if (retry === void 0) { retry = false; }
673
+ var isNewToken = false;
674
+ return this.getWithAuth(retry)
675
+ .then(function (res) {
676
+ isNewToken = _this._lastToken !== res;
677
+ _this._lastToken = res;
678
+ return res;
679
+ })
680
+ .then(promiseFactory)
681
+ .catch(function (err) {
682
+ // Only retry if the result is unauthorized and the last token isn't the same as the new one.
683
+ if ('code' in err &&
684
+ err.code === Code.UNAUTHORIZED &&
685
+ !retry &&
686
+ isNewToken) {
687
+ logDebug('Retrying due to unauthorized');
688
+ return _this.withRetry(promiseFactory, true);
689
+ }
690
+ throw err;
691
+ });
692
+ };
641
693
  return RESTTransport;
642
694
  }());
643
695
 
@@ -657,16 +709,26 @@ var RESTTransport = /** @class */ (function () {
657
709
  * See the License for the specific language governing permissions and
658
710
  * limitations under the License.
659
711
  */
660
- function mutationRef(dcInstance, queryName, variables) {
712
+ /**
713
+ *
714
+ * @param dcInstance Data Connect instance
715
+ * @param mutationName name of mutation
716
+ * @param variables variables to send with mutation
717
+ * @returns `MutationRef`
718
+ */
719
+ function mutationRef(dcInstance, mutationName, variables) {
661
720
  dcInstance.setInitialized();
662
721
  var ref = {
663
722
  dataConnect: dcInstance,
664
- name: queryName,
723
+ name: mutationName,
665
724
  refType: MUTATION_STR,
666
725
  variables: variables
667
726
  };
668
727
  return ref;
669
728
  }
729
+ /**
730
+ * @internal
731
+ */
670
732
  var MutationManager = /** @class */ (function () {
671
733
  function MutationManager(_transport) {
672
734
  this._transport = _transport;
@@ -688,6 +750,11 @@ var MutationManager = /** @class */ (function () {
688
750
  };
689
751
  return MutationManager;
690
752
  }());
753
+ /**
754
+ * Execute Mutation
755
+ * @param mutationRef mutation to execute
756
+ * @returns `MutationRef`
757
+ */
691
758
  function executeMutation(mutationRef) {
692
759
  return mutationRef.dataConnect._mutationManager.executeMutation(mutationRef);
693
760
  }
@@ -722,6 +789,9 @@ function parseOptions(fullHost) {
722
789
  var port = Number(portAsString);
723
790
  return { host: host, port: port, sslEnabled: isSecure };
724
791
  }
792
+ /**
793
+ * Class representing Firebase Data Connect
794
+ */
725
795
  var DataConnect = /** @class */ (function () {
726
796
  function DataConnect(app,
727
797
  // TODO(mtewani): Replace with _dataConnectOptions in the future
@@ -731,6 +801,7 @@ var DataConnect = /** @class */ (function () {
731
801
  this._authProvider = _authProvider;
732
802
  this.isEmulator = false;
733
803
  this.initialized = false;
804
+ this._isUsingGeneratedSdk = false;
734
805
  if (typeof process !== 'undefined' && process.env) {
735
806
  var host = process.env[FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR];
736
807
  if (host) {
@@ -740,6 +811,14 @@ var DataConnect = /** @class */ (function () {
740
811
  }
741
812
  }
742
813
  }
814
+ /*
815
+ @internal
816
+ */
817
+ DataConnect.prototype._useGeneratedSdk = function () {
818
+ if (!this._isUsingGeneratedSdk) {
819
+ this._isUsingGeneratedSdk = true;
820
+ }
821
+ };
743
822
  DataConnect.prototype._delete = function () {
744
823
  app._removeServiceInstance(this.app, 'data-connect', JSON.stringify(this.getSettings()));
745
824
  return Promise.resolve();
@@ -761,7 +840,7 @@ var DataConnect = /** @class */ (function () {
761
840
  this._authTokenProvider = new FirebaseAuthProvider(this.app.name, this.app.options, this._authProvider);
762
841
  }
763
842
  this.initialized = true;
764
- this._transport = new this._transportClass(this.dataConnectOptions, this.app.options.apiKey, this._authTokenProvider);
843
+ this._transport = new this._transportClass(this.dataConnectOptions, this.app.options.apiKey, this._authTokenProvider, undefined, this._isUsingGeneratedSdk);
765
844
  if (this._transportOptions) {
766
845
  this._transport.useEmulator(this._transportOptions.host, this._transportOptions.port, this._transportOptions.sslEnabled);
767
846
  }
@@ -778,6 +857,13 @@ var DataConnect = /** @class */ (function () {
778
857
  };
779
858
  return DataConnect;
780
859
  }());
860
+ /**
861
+ * Connect to the DataConnect Emulator
862
+ * @param dc Data Connect instance
863
+ * @param host host of emulator server
864
+ * @param port port of emulator server
865
+ * @param sslEnabled use https
866
+ */
781
867
  function connectDataConnectEmulator(dc, host, port, sslEnabled) {
782
868
  if (sslEnabled === void 0) { sslEnabled = false; }
783
869
  dc.enableEmulator({ host: host, port: port, sslEnabled: sslEnabled });
@@ -793,7 +879,7 @@ function getDataConnect(appOrOptions, optionalOptions) {
793
879
  dcOptions = optionalOptions;
794
880
  app$1 = appOrOptions;
795
881
  }
796
- if (!app$1) {
882
+ if (!app$1 || Object.keys(app$1).length === 0) {
797
883
  app$1 = app.getApp();
798
884
  }
799
885
  var provider = app._getProvider(app$1, 'data-connect');
@@ -807,9 +893,7 @@ function getDataConnect(appOrOptions, optionalOptions) {
807
893
  return dcInstance;
808
894
  }
809
895
  }
810
- if (!dcOptions) {
811
- throw new DataConnectError(Code.INVALID_ARGUMENT, 'DC Option Required');
812
- }
896
+ validateDCOptions(dcOptions);
813
897
  logDebug('Creating new DataConnect instance');
814
898
  // Initialize with options.
815
899
  return provider.initialize({
@@ -817,6 +901,29 @@ function getDataConnect(appOrOptions, optionalOptions) {
817
901
  options: dcOptions
818
902
  });
819
903
  }
904
+ /**
905
+ *
906
+ * @param dcOptions
907
+ * @returns {void}
908
+ * @internal
909
+ */
910
+ function validateDCOptions(dcOptions) {
911
+ var fields = ['connector', 'location', 'service'];
912
+ if (!dcOptions) {
913
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'DC Option Required');
914
+ }
915
+ fields.forEach(function (field) {
916
+ if (dcOptions[field] === null || dcOptions[field] === undefined) {
917
+ throw new DataConnectError(Code.INVALID_ARGUMENT, "".concat(field, " Required"));
918
+ }
919
+ });
920
+ return true;
921
+ }
922
+ /**
923
+ * Delete DataConnect instance
924
+ * @param dataConnect DataConnect instance
925
+ * @returns
926
+ */
820
927
  function terminate(dataConnect) {
821
928
  return dataConnect._delete();
822
929
  // TODO(mtewani): Stop pending tasks
@@ -832,6 +939,9 @@ function registerDataConnect(variant) {
832
939
  if (settings) {
833
940
  newOpts = JSON.parse(settings);
834
941
  }
942
+ if (!app.options.projectId) {
943
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'Project ID must be provided. Did you pass in a proper projectId to initializeApp?');
944
+ }
835
945
  return new DataConnect(app, tslib.__assign(tslib.__assign({}, newOpts), { projectId: app.options.projectId }), authProvider);
836
946
  }, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
837
947
  app.registerVersion(name, version, variant);
@@ -855,9 +965,22 @@ function registerDataConnect(variant) {
855
965
  * See the License for the specific language governing permissions and
856
966
  * limitations under the License.
857
967
  */
968
+ /**
969
+ * Execute Query
970
+ * @param queryRef query to execute.
971
+ * @returns `QueryPromise`
972
+ */
858
973
  function executeQuery(queryRef) {
859
974
  return queryRef.dataConnect._queryManager.executeQuery(queryRef);
860
975
  }
976
+ /**
977
+ * Execute Query
978
+ * @param dcInstance Data Connect instance to use.
979
+ * @param queryName Query to execute
980
+ * @param variables Variables to execute with
981
+ * @param initialCache initial cache to use for client hydration
982
+ * @returns `QueryRef`
983
+ */
861
984
  function queryRef(dcInstance, queryName, variables, initialCache) {
862
985
  dcInstance.setInitialized();
863
986
  dcInstance._queryManager.track(queryName, variables, initialCache);
@@ -868,6 +991,11 @@ function queryRef(dcInstance, queryName, variables, initialCache) {
868
991
  variables: variables
869
992
  };
870
993
  }
994
+ /**
995
+ * Converts serialized ref to query ref
996
+ * @param serializedRef ref to convert to `QueryRef`
997
+ * @returns `QueryRef`
998
+ */
871
999
  function toQueryRef(serializedRef) {
872
1000
  var _a = serializedRef.refInfo, name = _a.name, variables = _a.variables, connectorConfig = _a.connectorConfig;
873
1001
  return queryRef(getDataConnect(connectorConfig), name, variables);
@@ -889,6 +1017,57 @@ function toQueryRef(serializedRef) {
889
1017
  * See the License for the specific language governing permissions and
890
1018
  * limitations under the License.
891
1019
  */
1020
+ /**
1021
+ * The generated SDK will allow the user to pass in either the variable or the data connect instance with the variable,
1022
+ * and this function validates the variables and returns back the DataConnect instance and variables based on the arguments passed in.
1023
+ * @param connectorConfig
1024
+ * @param dcOrVars
1025
+ * @param vars
1026
+ * @param validateVars
1027
+ * @returns {DataConnect} and {Variables} instance
1028
+ * @internal
1029
+ */
1030
+ function validateArgs(connectorConfig, dcOrVars, vars, validateVars) {
1031
+ var dcInstance;
1032
+ var realVars;
1033
+ if (dcOrVars && 'enableEmulator' in dcOrVars) {
1034
+ dcInstance = dcOrVars;
1035
+ realVars = vars;
1036
+ }
1037
+ else {
1038
+ dcInstance = getDataConnect(connectorConfig);
1039
+ realVars = dcOrVars;
1040
+ }
1041
+ if (!dcInstance || (!realVars && validateVars)) {
1042
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'Variables required.');
1043
+ }
1044
+ return { dc: dcInstance, vars: realVars };
1045
+ }
1046
+
1047
+ /**
1048
+ * @license
1049
+ * Copyright 2024 Google LLC
1050
+ *
1051
+ * Licensed under the Apache License, Version 2.0 (the "License");
1052
+ * you may not use this file except in compliance with the License.
1053
+ * You may obtain a copy of the License at
1054
+ *
1055
+ * http://www.apache.org/licenses/LICENSE-2.0
1056
+ *
1057
+ * Unless required by applicable law or agreed to in writing, software
1058
+ * distributed under the License is distributed on an "AS IS" BASIS,
1059
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1060
+ * See the License for the specific language governing permissions and
1061
+ * limitations under the License.
1062
+ */
1063
+ /**
1064
+ * Subscribe to a `QueryRef`
1065
+ * @param queryRefOrSerializedResult query ref or serialized result.
1066
+ * @param observerOrOnNext observer object or next function.
1067
+ * @param onError Callback to call when error gets thrown.
1068
+ * @param onComplete Called when subscription completes.
1069
+ * @returns `SubscriptionOptions`
1070
+ */
892
1071
  function subscribe(queryRefOrSerializedResult, observerOrOnNext, onError, onComplete) {
893
1072
  var ref;
894
1073
  var initialCache;
@@ -958,4 +1137,6 @@ exports.setLogLevel = setLogLevel;
958
1137
  exports.subscribe = subscribe;
959
1138
  exports.terminate = terminate;
960
1139
  exports.toQueryRef = toQueryRef;
1140
+ exports.validateArgs = validateArgs;
1141
+ exports.validateDCOptions = validateDCOptions;
961
1142
  //# sourceMappingURL=index.node.cjs.js.map