@firebase/data-connect 0.0.3-dataconnect-preview.d986d4bf2 → 0.1.0

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.
@@ -4,7 +4,7 @@ import { FirebaseError } from '@firebase/util';
4
4
  import { Logger } from '@firebase/logger';
5
5
 
6
6
  const name = "@firebase/data-connect";
7
- const version = "0.0.3-dataconnect-preview.d986d4bf2";
7
+ const version = "0.1.0";
8
8
 
9
9
  /**
10
10
  * @license
@@ -32,6 +32,60 @@ function setSDKVersion(version) {
32
32
  SDK_VERSION = version;
33
33
  }
34
34
 
35
+ /**
36
+ * @license
37
+ * Copyright 2024 Google LLC
38
+ *
39
+ * Licensed under the Apache License, Version 2.0 (the "License");
40
+ * you may not use this file except in compliance with the License.
41
+ * You may obtain a copy of the License at
42
+ *
43
+ * http://www.apache.org/licenses/LICENSE-2.0
44
+ *
45
+ * Unless required by applicable law or agreed to in writing, software
46
+ * distributed under the License is distributed on an "AS IS" BASIS,
47
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48
+ * See the License for the specific language governing permissions and
49
+ * limitations under the License.
50
+ */
51
+ /**
52
+ * @internal
53
+ * Abstraction around AppCheck's token fetching capabilities.
54
+ */
55
+ class AppCheckTokenProvider {
56
+ constructor(appName_, appCheckProvider) {
57
+ this.appName_ = appName_;
58
+ this.appCheckProvider = appCheckProvider;
59
+ this.appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({ optional: true });
60
+ if (!this.appCheck) {
61
+ void (appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.get().then(appCheck => (this.appCheck = appCheck)).catch());
62
+ }
63
+ }
64
+ getToken(forceRefresh) {
65
+ if (!this.appCheck) {
66
+ return new Promise((resolve, reject) => {
67
+ // Support delayed initialization of FirebaseAppCheck. This allows our
68
+ // customers to initialize the RTDB SDK before initializing Firebase
69
+ // AppCheck and ensures that all requests are authenticated if a token
70
+ // becomes available before the timoeout below expires.
71
+ setTimeout(() => {
72
+ if (this.appCheck) {
73
+ this.getToken(forceRefresh).then(resolve, reject);
74
+ }
75
+ else {
76
+ resolve(null);
77
+ }
78
+ }, 0);
79
+ });
80
+ }
81
+ return this.appCheck.getToken(forceRefresh);
82
+ }
83
+ addTokenChangeListener(listener) {
84
+ var _a;
85
+ void ((_a = this.appCheckProvider) === null || _a === void 0 ? void 0 : _a.get().then(appCheck => appCheck.addTokenListener(listener)));
86
+ }
87
+ }
88
+
35
89
  /**
36
90
  * @license
37
91
  * Copyright 2024 Google LLC
@@ -122,6 +176,7 @@ function logError(msg) {
122
176
  * See the License for the specific language governing permissions and
123
177
  * limitations under the License.
124
178
  */
179
+ // @internal
125
180
  class FirebaseAuthProvider {
126
181
  constructor(_appName, _options, _authProvider) {
127
182
  this._appName = _appName;
@@ -405,7 +460,7 @@ function urlBuilder(projectConfig, transportOptions) {
405
460
  logError('Port type is of an invalid type');
406
461
  throw new DataConnectError(Code.INVALID_ARGUMENT, 'Incorrect type for port passed in!');
407
462
  }
408
- return `${baseUrl}/v1alpha/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`;
463
+ return `${baseUrl}/v1beta/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`;
409
464
  }
410
465
  function addToken(url, apiKey) {
411
466
  if (!apiKey) {
@@ -440,7 +495,7 @@ function getGoogApiClientValue(_isUsingGen) {
440
495
  }
441
496
  return str;
442
497
  }
443
- function dcFetch(url, body, { signal }, accessToken, _isUsingGen) {
498
+ function dcFetch(url, body, { signal }, appId, accessToken, appCheckToken, _isUsingGen) {
444
499
  if (!connectFetch) {
445
500
  throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!');
446
501
  }
@@ -451,6 +506,12 @@ function dcFetch(url, body, { signal }, accessToken, _isUsingGen) {
451
506
  if (accessToken) {
452
507
  headers['X-Firebase-Auth-Token'] = accessToken;
453
508
  }
509
+ if (appId) {
510
+ headers['x-firebase-gmpid'] = appId;
511
+ }
512
+ if (appCheckToken) {
513
+ headers['X-Firebase-AppCheck'] = appCheckToken;
514
+ }
454
515
  const bodyStr = JSON.stringify(body);
455
516
  logDebug(`Making request out to ${url} with body: ${bodyStr}`);
456
517
  return connectFetch(url, {
@@ -513,10 +574,12 @@ function getMessage(obj) {
513
574
  * limitations under the License.
514
575
  */
515
576
  class RESTTransport {
516
- constructor(options, apiKey, authProvider, transportOptions, _isUsingGen = false) {
517
- var _a;
577
+ constructor(options, apiKey, appId, authProvider, appCheckProvider, transportOptions, _isUsingGen = false) {
578
+ var _a, _b;
518
579
  this.apiKey = apiKey;
580
+ this.appId = appId;
519
581
  this.authProvider = authProvider;
582
+ this.appCheckProvider = appCheckProvider;
520
583
  this._isUsingGen = _isUsingGen;
521
584
  this._host = '';
522
585
  this._location = 'l';
@@ -524,7 +587,7 @@ class RESTTransport {
524
587
  this._secure = true;
525
588
  this._project = 'p';
526
589
  this._accessToken = null;
527
- this._authInitialized = false;
590
+ this._appCheckToken = null;
528
591
  this._lastToken = null;
529
592
  // TODO(mtewani): Update U to include shape of body defined in line 13.
530
593
  this.invokeQuery = (queryName, body) => {
@@ -535,7 +598,7 @@ class RESTTransport {
535
598
  operationName: queryName,
536
599
  variables: body
537
600
  }, // TODO(mtewani): This is a patch, fix this.
538
- abortController, this._accessToken, this._isUsingGen));
601
+ abortController, this.appId, this._accessToken, this._appCheckToken, this._isUsingGen));
539
602
  return {
540
603
  then: withAuth.then.bind(withAuth),
541
604
  catch: withAuth.catch.bind(withAuth)
@@ -548,7 +611,7 @@ class RESTTransport {
548
611
  name: `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`,
549
612
  operationName: mutationName,
550
613
  variables: body
551
- }, abortController, this._accessToken, this._isUsingGen);
614
+ }, abortController, this.appId, this._accessToken, this._appCheckToken, this._isUsingGen);
552
615
  });
553
616
  return {
554
617
  then: taskResult.then.bind(taskResult),
@@ -582,6 +645,11 @@ class RESTTransport {
582
645
  logDebug(`New Token Available: ${token}`);
583
646
  this._accessToken = token;
584
647
  });
648
+ (_b = this.appCheckProvider) === null || _b === void 0 ? void 0 : _b.addTokenChangeListener(result => {
649
+ const { token } = result;
650
+ logDebug(`New App Check Token Available: ${token}`);
651
+ this._appCheckToken = token;
652
+ });
585
653
  }
586
654
  get endpointUrl() {
587
655
  return urlBuilder({
@@ -603,23 +671,25 @@ class RESTTransport {
603
671
  onTokenChanged(newToken) {
604
672
  this._accessToken = newToken;
605
673
  }
606
- getWithAuth(forceToken = false) {
674
+ async getWithAuth(forceToken = false) {
675
+ var _a;
607
676
  let starterPromise = new Promise(resolve => resolve(this._accessToken));
608
- if (!this._authInitialized) {
609
- if (this.authProvider) {
610
- starterPromise = this.authProvider
611
- .getToken(/*forceToken=*/ forceToken)
612
- .then(data => {
613
- if (!data) {
614
- return null;
615
- }
616
- this._accessToken = data.accessToken;
617
- return this._accessToken;
618
- });
619
- }
620
- else {
621
- starterPromise = new Promise(resolve => resolve(''));
622
- }
677
+ if (this.appCheckProvider) {
678
+ this._appCheckToken = (_a = (await this.appCheckProvider.getToken())) === null || _a === void 0 ? void 0 : _a.token;
679
+ }
680
+ if (this.authProvider) {
681
+ starterPromise = this.authProvider
682
+ .getToken(/*forceToken=*/ forceToken)
683
+ .then(data => {
684
+ if (!data) {
685
+ return null;
686
+ }
687
+ this._accessToken = data.accessToken;
688
+ return this._accessToken;
689
+ });
690
+ }
691
+ else {
692
+ starterPromise = new Promise(resolve => resolve(''));
623
693
  }
624
694
  return starterPromise;
625
695
  }
@@ -745,14 +815,16 @@ function parseOptions(fullHost) {
745
815
  * Class representing Firebase Data Connect
746
816
  */
747
817
  class DataConnect {
818
+ // @internal
748
819
  constructor(app,
749
820
  // TODO(mtewani): Replace with _dataConnectOptions in the future
750
- dataConnectOptions, _authProvider) {
821
+ dataConnectOptions, _authProvider, _appCheckProvider) {
751
822
  this.app = app;
752
823
  this.dataConnectOptions = dataConnectOptions;
753
824
  this._authProvider = _authProvider;
825
+ this._appCheckProvider = _appCheckProvider;
754
826
  this.isEmulator = false;
755
- this.initialized = false;
827
+ this._initialized = false;
756
828
  this._isUsingGeneratedSdk = false;
757
829
  if (typeof process !== 'undefined' && process.env) {
758
830
  const host = process.env[FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR];
@@ -763,9 +835,7 @@ class DataConnect {
763
835
  }
764
836
  }
765
837
  }
766
- /*
767
- @internal
768
- */
838
+ // @internal
769
839
  _useGeneratedSdk() {
770
840
  if (!this._isUsingGeneratedSdk) {
771
841
  this._isUsingGeneratedSdk = true;
@@ -775,13 +845,15 @@ class DataConnect {
775
845
  _removeServiceInstance(this.app, 'data-connect', JSON.stringify(this.getSettings()));
776
846
  return Promise.resolve();
777
847
  }
848
+ // @internal
778
849
  getSettings() {
779
850
  const copy = JSON.parse(JSON.stringify(this.dataConnectOptions));
780
851
  delete copy.projectId;
781
852
  return copy;
782
853
  }
854
+ // @internal
783
855
  setInitialized() {
784
- if (this.initialized) {
856
+ if (this._initialized) {
785
857
  return;
786
858
  }
787
859
  if (this._transportClass === undefined) {
@@ -791,16 +863,20 @@ class DataConnect {
791
863
  if (this._authProvider) {
792
864
  this._authTokenProvider = new FirebaseAuthProvider(this.app.name, this.app.options, this._authProvider);
793
865
  }
794
- this.initialized = true;
795
- this._transport = new this._transportClass(this.dataConnectOptions, this.app.options.apiKey, this._authTokenProvider, undefined, this._isUsingGeneratedSdk);
866
+ if (this._appCheckProvider) {
867
+ this._appCheckTokenProvider = new AppCheckTokenProvider(this.app.name, this._appCheckProvider);
868
+ }
869
+ this._initialized = true;
870
+ this._transport = new this._transportClass(this.dataConnectOptions, this.app.options.apiKey, this.app.options.appId, this._authTokenProvider, this._appCheckTokenProvider, undefined, this._isUsingGeneratedSdk);
796
871
  if (this._transportOptions) {
797
872
  this._transport.useEmulator(this._transportOptions.host, this._transportOptions.port, this._transportOptions.sslEnabled);
798
873
  }
799
874
  this._queryManager = new QueryManager(this._transport);
800
875
  this._mutationManager = new MutationManager(this._transport);
801
876
  }
877
+ // @internal
802
878
  enableEmulator(transportOptions) {
803
- if (this.initialized) {
879
+ if (this._initialized) {
804
880
  logError('enableEmulator called after initialization');
805
881
  throw new DataConnectError(Code.ALREADY_INITIALIZED, 'DataConnect instance already initialized!');
806
882
  }
@@ -900,6 +976,7 @@ function registerDataConnect(variant) {
900
976
  _registerComponent(new Component('data-connect', (container, { instanceIdentifier: settings, options }) => {
901
977
  const app = container.getProvider('app').getImmediate();
902
978
  const authProvider = container.getProvider('auth-internal');
979
+ const appCheckProvider = container.getProvider('app-check-internal');
903
980
  let newOpts = options;
904
981
  if (settings) {
905
982
  newOpts = JSON.parse(settings);
@@ -907,7 +984,7 @@ function registerDataConnect(variant) {
907
984
  if (!app.options.projectId) {
908
985
  throw new DataConnectError(Code.INVALID_ARGUMENT, 'Project ID must be provided. Did you pass in a proper projectId to initializeApp?');
909
986
  }
910
- return new DataConnect(app, Object.assign(Object.assign({}, newOpts), { projectId: app.options.projectId }), authProvider);
987
+ return new DataConnect(app, Object.assign(Object.assign({}, newOpts), { projectId: app.options.projectId }), authProvider, appCheckProvider);
911
988
  }, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
912
989
  registerVersion(name, version, variant);
913
990
  // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
@@ -1071,5 +1148,5 @@ function subscribe(queryRefOrSerializedResult, observerOrOnNext, onError, onComp
1071
1148
  */
1072
1149
  registerDataConnect();
1073
1150
 
1074
- export { DataConnect, FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR, FirebaseAuthProvider, MUTATION_STR, MutationManager, QUERY_STR, SOURCE_CACHE, SOURCE_SERVER, connectDataConnectEmulator, executeMutation, executeQuery, getDataConnect, mutationRef, parseOptions, queryRef, setLogLevel, subscribe, terminate, toQueryRef, validateArgs, validateDCOptions };
1151
+ export { DataConnect, MUTATION_STR, MutationManager, QUERY_STR, SOURCE_CACHE, SOURCE_SERVER, connectDataConnectEmulator, executeMutation, executeQuery, getDataConnect, mutationRef, parseOptions, queryRef, setLogLevel, subscribe, terminate, toQueryRef, validateArgs, validateDCOptions };
1075
1152
  //# sourceMappingURL=index.esm2017.js.map