@firebase/data-connect 0.0.1-dataconnect-preview.f2ddc3d7b

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 (66) hide show
  1. package/dist/index.cjs.js +965 -0
  2. package/dist/index.cjs.js.map +1 -0
  3. package/dist/index.esm2017.js +942 -0
  4. package/dist/index.esm2017.js.map +1 -0
  5. package/dist/index.esm5.js +966 -0
  6. package/dist/index.esm5.js.map +1 -0
  7. package/dist/index.node.cjs.js +984 -0
  8. package/dist/index.node.cjs.js.map +1 -0
  9. package/dist/internal.d.ts +297 -0
  10. package/dist/node-esm/index.node.esm.js +937 -0
  11. package/dist/node-esm/index.node.esm.js.map +1 -0
  12. package/dist/node-esm/package.json +1 -0
  13. package/dist/node-esm/src/api/DataConnect.d.ts +70 -0
  14. package/dist/node-esm/src/api/Mutation.d.ts +36 -0
  15. package/dist/node-esm/src/api/Reference.d.ts +45 -0
  16. package/dist/node-esm/src/api/index.d.ts +22 -0
  17. package/dist/node-esm/src/api/query.d.ts +46 -0
  18. package/dist/node-esm/src/api.browser.d.ts +29 -0
  19. package/dist/node-esm/src/api.node.d.ts +17 -0
  20. package/dist/node-esm/src/core/FirebaseAuthProvider.d.ts +44 -0
  21. package/dist/node-esm/src/core/QueryManager.d.ts +36 -0
  22. package/dist/node-esm/src/core/error.d.ts +50 -0
  23. package/dist/node-esm/src/core/version.d.ts +23 -0
  24. package/dist/node-esm/src/index.d.ts +29 -0
  25. package/dist/node-esm/src/index.node.d.ts +18 -0
  26. package/dist/node-esm/src/logger.d.ts +20 -0
  27. package/dist/node-esm/src/network/fetch.d.ts +21 -0
  28. package/dist/node-esm/src/network/index.d.ts +17 -0
  29. package/dist/node-esm/src/network/transport/index.d.ts +45 -0
  30. package/dist/node-esm/src/network/transport/rest.d.ts +56 -0
  31. package/dist/node-esm/src/register.d.ts +1 -0
  32. package/dist/node-esm/src/util/encoder.d.ts +19 -0
  33. package/dist/node-esm/src/util/map.d.ts +17 -0
  34. package/dist/node-esm/src/util/url.d.ts +19 -0
  35. package/dist/node-esm/test/emulatorSeeder.d.ts +22 -0
  36. package/dist/node-esm/test/queries.test.d.ts +17 -0
  37. package/dist/node-esm/test/util.d.ts +26 -0
  38. package/dist/private.d.ts +291 -0
  39. package/dist/public.d.ts +187 -0
  40. package/dist/src/api/DataConnect.d.ts +70 -0
  41. package/dist/src/api/Mutation.d.ts +36 -0
  42. package/dist/src/api/Reference.d.ts +45 -0
  43. package/dist/src/api/index.d.ts +22 -0
  44. package/dist/src/api/query.d.ts +46 -0
  45. package/dist/src/api.browser.d.ts +29 -0
  46. package/dist/src/api.node.d.ts +17 -0
  47. package/dist/src/core/FirebaseAuthProvider.d.ts +44 -0
  48. package/dist/src/core/QueryManager.d.ts +36 -0
  49. package/dist/src/core/error.d.ts +50 -0
  50. package/dist/src/core/version.d.ts +23 -0
  51. package/dist/src/index.d.ts +29 -0
  52. package/dist/src/index.node.d.ts +18 -0
  53. package/dist/src/logger.d.ts +20 -0
  54. package/dist/src/network/fetch.d.ts +21 -0
  55. package/dist/src/network/index.d.ts +17 -0
  56. package/dist/src/network/transport/index.d.ts +45 -0
  57. package/dist/src/network/transport/rest.d.ts +56 -0
  58. package/dist/src/register.d.ts +1 -0
  59. package/dist/src/tsdoc-metadata.json +11 -0
  60. package/dist/src/util/encoder.d.ts +19 -0
  61. package/dist/src/util/map.d.ts +17 -0
  62. package/dist/src/util/url.d.ts +19 -0
  63. package/dist/test/emulatorSeeder.d.ts +22 -0
  64. package/dist/test/queries.test.d.ts +17 -0
  65. package/dist/test/util.d.ts +26 -0
  66. package/package.json +76 -0
@@ -0,0 +1,942 @@
1
+ import { _removeServiceInstance, getApp, _getProvider, _registerComponent, registerVersion, SDK_VERSION as SDK_VERSION$1 } from '@firebase/app';
2
+ import { Component } from '@firebase/component';
3
+ import { Logger } from '@firebase/logger';
4
+ import { FirebaseError } from '@firebase/util';
5
+
6
+ const name = "@firebase/data-connect";
7
+ const version = "0.0.1";
8
+
9
+ /**
10
+ * @license
11
+ * Copyright 2024 Google LLC
12
+ *
13
+ * Licensed under the Apache License, Version 2.0 (the "License");
14
+ * you may not use this file except in compliance with the License.
15
+ * You may obtain a copy of the License at
16
+ *
17
+ * http://www.apache.org/licenses/LICENSE-2.0
18
+ *
19
+ * Unless required by applicable law or agreed to in writing, software
20
+ * distributed under the License is distributed on an "AS IS" BASIS,
21
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ * See the License for the specific language governing permissions and
23
+ * limitations under the License.
24
+ */
25
+ /** The semver (www.semver.org) version of the SDK. */
26
+ let SDK_VERSION = '';
27
+ /**
28
+ * SDK_VERSION should be set before any database instance is created
29
+ * @internal
30
+ */
31
+ function setSDKVersion(version) {
32
+ SDK_VERSION = version;
33
+ }
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
+ const logger = new Logger('@firebase/data-connect');
52
+ function setLogLevel(logLevel) {
53
+ logger.setLogLevel(logLevel);
54
+ }
55
+ function logDebug(msg) {
56
+ // if (logger.logLevel <= LogLevel.DEBUG) {
57
+ logger.debug(`DataConnect (${SDK_VERSION}): ${msg}`);
58
+ // }
59
+ }
60
+ function logError(msg) {
61
+ // if (logger.logLevel <= LogLevel.ERROR) {
62
+ logger.error(`DataConnect (${SDK_VERSION}): ${msg}`);
63
+ // }
64
+ }
65
+
66
+ /**
67
+ * @license
68
+ * Copyright 2024 Google LLC
69
+ *
70
+ * Licensed under the Apache License, Version 2.0 (the "License");
71
+ * you may not use this file except in compliance with the License.
72
+ * You may obtain a copy of the License at
73
+ *
74
+ * http://www.apache.org/licenses/LICENSE-2.0
75
+ *
76
+ * Unless required by applicable law or agreed to in writing, software
77
+ * distributed under the License is distributed on an "AS IS" BASIS,
78
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79
+ * See the License for the specific language governing permissions and
80
+ * limitations under the License.
81
+ */
82
+ class FirebaseAuthProvider {
83
+ constructor(appName, options, authProvider_) {
84
+ this.appName = appName;
85
+ this.options = options;
86
+ this.authProvider_ = authProvider_;
87
+ this.auth_ = authProvider_.getImmediate({ optional: true });
88
+ if (!this.auth_) {
89
+ authProvider_.onInit(auth => (this.auth_ = auth));
90
+ }
91
+ }
92
+ getToken(forceRefresh) {
93
+ if (!this.auth_) {
94
+ return new Promise((resolve, reject) => {
95
+ setTimeout(() => {
96
+ if (this.auth_) {
97
+ this.getToken(forceRefresh).then(resolve, reject);
98
+ }
99
+ else {
100
+ resolve(null);
101
+ }
102
+ }, 0);
103
+ });
104
+ }
105
+ return this.auth_.getToken(forceRefresh).catch(error => {
106
+ if (error && error.code === 'auth/token-not-initialized') {
107
+ logDebug('Got auth/token-not-initialized error. Treating as null token.');
108
+ return null;
109
+ }
110
+ else {
111
+ logError('Error received when attempting to retrieve token: ' +
112
+ JSON.stringify(error));
113
+ return Promise.reject(error);
114
+ }
115
+ });
116
+ }
117
+ addTokenChangeListener(listener) {
118
+ var _a;
119
+ (_a = this.auth_) === null || _a === void 0 ? void 0 : _a.addAuthTokenListener(listener);
120
+ }
121
+ removeTokenChangeListener(listener) {
122
+ this.authProvider_
123
+ .get()
124
+ .then(auth => auth.removeAuthTokenListener(listener));
125
+ }
126
+ }
127
+ class EmulatorTokenProvider {
128
+ constructor(accessToken) {
129
+ this.accessToken = accessToken;
130
+ }
131
+ getToken(forceRefresh) {
132
+ return Promise.resolve({
133
+ accessToken: this.accessToken
134
+ });
135
+ }
136
+ addTokenChangeListener(listener) {
137
+ // Invoke the listener immediately to match the behavior in Firebase Auth
138
+ // (see packages/auth/src/auth.js#L1807)
139
+ listener(this.accessToken);
140
+ }
141
+ removeTokenChangeListener(listener) { }
142
+ notifyForInvalidToken() { }
143
+ }
144
+ /** A string that is treated as an admin access token by the RTDB emulator. Used by Admin SDK. */
145
+ EmulatorTokenProvider.OWNER = 'owner';
146
+
147
+ /**
148
+ * @license
149
+ * Copyright 2024 Google LLC
150
+ *
151
+ * Licensed under the Apache License, Version 2.0 (the "License");
152
+ * you may not use this file except in compliance with the License.
153
+ * You may obtain a copy of the License at
154
+ *
155
+ * http://www.apache.org/licenses/LICENSE-2.0
156
+ *
157
+ * Unless required by applicable law or agreed to in writing, software
158
+ * distributed under the License is distributed on an "AS IS" BASIS,
159
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
160
+ * See the License for the specific language governing permissions and
161
+ * limitations under the License.
162
+ */
163
+ const QueryStr = 'query';
164
+ const MutationStr = 'mutation';
165
+ const SOURCE_SERVER = 'SERVER';
166
+ const SOURCE_CACHE = 'CACHE';
167
+
168
+ /**
169
+ * @license
170
+ * Copyright 2024 Google LLC
171
+ *
172
+ * Licensed under the Apache License, Version 2.0 (the "License");
173
+ * you may not use this file except in compliance with the License.
174
+ * You may obtain a copy of the License at
175
+ *
176
+ * http://www.apache.org/licenses/LICENSE-2.0
177
+ *
178
+ * Unless required by applicable law or agreed to in writing, software
179
+ * distributed under the License is distributed on an "AS IS" BASIS,
180
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
181
+ * See the License for the specific language governing permissions and
182
+ * limitations under the License.
183
+ */
184
+ let encoderImpl;
185
+ function setEncoder(encoder) {
186
+ encoderImpl = encoder;
187
+ }
188
+ setEncoder(o => JSON.stringify(o));
189
+
190
+ /**
191
+ * @license
192
+ * Copyright 2024 Google LLC
193
+ *
194
+ * Licensed under the Apache License, Version 2.0 (the "License");
195
+ * you may not use this file except in compliance with the License.
196
+ * You may obtain a copy of the License at
197
+ *
198
+ * http://www.apache.org/licenses/LICENSE-2.0
199
+ *
200
+ * Unless required by applicable law or agreed to in writing, software
201
+ * distributed under the License is distributed on an "AS IS" BASIS,
202
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203
+ * See the License for the specific language governing permissions and
204
+ * limitations under the License.
205
+ */
206
+ function setIfNotExists(map, key, val) {
207
+ if (!map.has(key)) {
208
+ map.set(key, val);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * @license
214
+ * Copyright 2024 Google LLC
215
+ *
216
+ * Licensed under the Apache License, Version 2.0 (the "License");
217
+ * you may not use this file except in compliance with the License.
218
+ * You may obtain a copy of the License at
219
+ *
220
+ * http://www.apache.org/licenses/LICENSE-2.0
221
+ *
222
+ * Unless required by applicable law or agreed to in writing, software
223
+ * distributed under the License is distributed on an "AS IS" BASIS,
224
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
225
+ * See the License for the specific language governing permissions and
226
+ * limitations under the License.
227
+ */
228
+ function getRefSerializer(queryRef, data, source) {
229
+ return function toJSON() {
230
+ return {
231
+ data,
232
+ refInfo: {
233
+ name: queryRef.name,
234
+ variables: queryRef.variables,
235
+ connectorConfig: Object.assign({ projectId: queryRef.dataConnect.app.options.projectId }, queryRef.dataConnect.getSettings())
236
+ },
237
+ fetchTime: Date.now().toLocaleString(),
238
+ source
239
+ };
240
+ };
241
+ }
242
+ class QueryManager {
243
+ constructor(transport) {
244
+ this.transport = transport;
245
+ this._queries = new Map();
246
+ }
247
+ track(queryName, variables, initialCache) {
248
+ const ref = {
249
+ name: queryName,
250
+ variables,
251
+ refType: QueryStr
252
+ };
253
+ const key = encoderImpl(ref);
254
+ const newTrackedQuery = {
255
+ ref,
256
+ subscriptions: [],
257
+ currentCache: initialCache || null,
258
+ lastError: null
259
+ };
260
+ // @ts-ignore
261
+ setIfNotExists(this._queries, key, newTrackedQuery);
262
+ return this._queries.get(key);
263
+ }
264
+ addSubscription(queryRef, onResultCallback, onErrorCallback, initialCache) {
265
+ const key = encoderImpl({
266
+ name: queryRef.name,
267
+ variables: queryRef.variables,
268
+ refType: QueryStr
269
+ });
270
+ const trackedQuery = this._queries.get(key);
271
+ const subscription = {
272
+ userCallback: onResultCallback,
273
+ errCallback: onErrorCallback
274
+ };
275
+ const unsubscribe = () => {
276
+ const trackedQuery = this._queries.get(key);
277
+ trackedQuery.subscriptions = trackedQuery.subscriptions.filter(sub => sub !== subscription);
278
+ };
279
+ if (initialCache && trackedQuery.currentCache !== initialCache) {
280
+ logDebug('Initial cache found. Comparing dates.');
281
+ if (!trackedQuery.currentCache ||
282
+ (trackedQuery.currentCache &&
283
+ compareDates(trackedQuery.currentCache.fetchTime, initialCache.fetchTime))) {
284
+ trackedQuery.currentCache = initialCache;
285
+ }
286
+ }
287
+ if (trackedQuery.currentCache !== null) {
288
+ const cachedData = trackedQuery.currentCache.data;
289
+ onResultCallback({
290
+ data: cachedData,
291
+ source: SOURCE_CACHE,
292
+ ref: queryRef,
293
+ toJSON: getRefSerializer(queryRef, trackedQuery.currentCache.data, SOURCE_CACHE),
294
+ fetchTime: trackedQuery.currentCache.fetchTime
295
+ });
296
+ if (trackedQuery.lastError !== null && onErrorCallback) {
297
+ onErrorCallback(undefined);
298
+ }
299
+ }
300
+ trackedQuery.subscriptions.push({
301
+ userCallback: onResultCallback,
302
+ errCallback: onErrorCallback,
303
+ unsubscribe
304
+ });
305
+ if (!trackedQuery.currentCache) {
306
+ logDebug(`No cache available for query ${queryRef.name} with variables ${JSON.stringify(queryRef.variables)}. Calling executeQuery.`);
307
+ const promise = this.executeQuery(queryRef);
308
+ // We want to ignore the error and let subscriptions handle it
309
+ promise.then(undefined, err => { });
310
+ }
311
+ return unsubscribe;
312
+ }
313
+ executeQuery(queryRef) {
314
+ const key = encoderImpl({
315
+ name: queryRef.name,
316
+ variables: queryRef.variables,
317
+ refType: QueryStr
318
+ });
319
+ const trackedQuery = this._queries.get(key);
320
+ const result = this.transport.invokeQuery(queryRef.name, queryRef.variables);
321
+ const newR = result.then(res => {
322
+ const fetchTime = new Date().toString();
323
+ const result = Object.assign(Object.assign({}, res), { source: SOURCE_SERVER, ref: queryRef, toJSON: getRefSerializer(queryRef, res.data, SOURCE_SERVER), fetchTime });
324
+ trackedQuery.subscriptions.forEach(subscription => {
325
+ subscription.userCallback(result);
326
+ });
327
+ trackedQuery.currentCache = {
328
+ data: res.data,
329
+ source: SOURCE_CACHE,
330
+ fetchTime
331
+ };
332
+ return result;
333
+ }, err => {
334
+ trackedQuery.lastError = err;
335
+ trackedQuery.subscriptions.forEach(subscription => {
336
+ if (subscription.errCallback) {
337
+ subscription.errCallback(err);
338
+ }
339
+ });
340
+ throw err;
341
+ });
342
+ return newR;
343
+ }
344
+ enableEmulator(host, port) {
345
+ this.transport.useEmulator(host, port);
346
+ }
347
+ }
348
+ function compareDates(str1, str2) {
349
+ const date1 = new Date(str1);
350
+ const date2 = new Date(str2);
351
+ return date1.getTime() < date2.getTime();
352
+ }
353
+
354
+ /**
355
+ * @license
356
+ * Copyright 2024 Google LLC
357
+ *
358
+ * Licensed under the Apache License, Version 2.0 (the "License");
359
+ * you may not use this file except in compliance with the License.
360
+ * You may obtain a copy of the License at
361
+ *
362
+ * http://www.apache.org/licenses/LICENSE-2.0
363
+ *
364
+ * Unless required by applicable law or agreed to in writing, software
365
+ * distributed under the License is distributed on an "AS IS" BASIS,
366
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
367
+ * See the License for the specific language governing permissions and
368
+ * limitations under the License.
369
+ */
370
+ const Code = {
371
+ OTHER: 'other',
372
+ ALREADY_INITIALIZED: 'already-initialized',
373
+ NOT_INITIALIZED: 'not-initialized',
374
+ NOT_SUPPORTED: 'not-supported',
375
+ INVALID_ARGUMENT: 'invalid-argument',
376
+ PARTIAL_ERROR: 'partial-error'
377
+ };
378
+ /** An error returned by a DataConnect operation. */
379
+ class DataConnectError extends FirebaseError {
380
+ /** @hideconstructor */
381
+ constructor(
382
+ /**
383
+ * The backend error code associated with this error.
384
+ */
385
+ code,
386
+ /**
387
+ * A custom error description.
388
+ */
389
+ message) {
390
+ super(code, message);
391
+ this.code = code;
392
+ this.message = message;
393
+ // HACK: We write a toString property directly because Error is not a real
394
+ // class and so inheritance does not work correctly. We could alternatively
395
+ // do the same "back-door inheritance" trick that FirebaseError does.
396
+ this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;
397
+ }
398
+ }
399
+
400
+ /**
401
+ * @license
402
+ * Copyright 2024 Google LLC
403
+ *
404
+ * Licensed under the Apache License, Version 2.0 (the "License");
405
+ * you may not use this file except in compliance with the License.
406
+ * You may obtain a copy of the License at
407
+ *
408
+ * http://www.apache.org/licenses/LICENSE-2.0
409
+ *
410
+ * Unless required by applicable law or agreed to in writing, software
411
+ * distributed under the License is distributed on an "AS IS" BASIS,
412
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
413
+ * See the License for the specific language governing permissions and
414
+ * limitations under the License.
415
+ */
416
+ function urlBuilder(projectConfig, transportOptions) {
417
+ const { connector, location, projectId: project, service } = projectConfig;
418
+ const { host, sslEnabled, port } = transportOptions;
419
+ const protocol = sslEnabled ? 'https' : 'http';
420
+ const realHost = host || `firebasedataconnect.googleapis.com`;
421
+ let baseUrl = `${protocol}://${realHost}`;
422
+ if (typeof port === 'number') {
423
+ baseUrl += `:${port}`;
424
+ }
425
+ else if (typeof port !== 'undefined') {
426
+ logError('Port type is of an invalid type');
427
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'Incorrect type for port passed in!');
428
+ }
429
+ return `${baseUrl}/v1alpha/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`;
430
+ }
431
+ function addToken(url, apiKey) {
432
+ if (!apiKey) {
433
+ return url;
434
+ }
435
+ const newUrl = new URL(url);
436
+ newUrl.searchParams.append('key', apiKey);
437
+ return newUrl.toString();
438
+ }
439
+
440
+ /**
441
+ * @license
442
+ * Copyright 2024 Google LLC
443
+ *
444
+ * Licensed under the Apache License, Version 2.0 (the "License");
445
+ * you may not use this file except in compliance with the License.
446
+ * You may obtain a copy of the License at
447
+ *
448
+ * http://www.apache.org/licenses/LICENSE-2.0
449
+ *
450
+ * Unless required by applicable law or agreed to in writing, software
451
+ * distributed under the License is distributed on an "AS IS" BASIS,
452
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
453
+ * See the License for the specific language governing permissions and
454
+ * limitations under the License.
455
+ */
456
+ let connectFetch = globalThis.fetch;
457
+ function dcFetch(url, body, { signal }, accessToken) {
458
+ if (!connectFetch) {
459
+ throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!');
460
+ }
461
+ const headers = {
462
+ 'Content-Type': 'application/json'
463
+ };
464
+ if (accessToken) {
465
+ headers['X-Firebase-Auth-Token'] = accessToken;
466
+ }
467
+ const bodyStr = JSON.stringify(body);
468
+ logDebug(`Making request out to ${url} with body: ${bodyStr}`);
469
+ return connectFetch(url, {
470
+ body: bodyStr,
471
+ method: 'POST',
472
+ headers,
473
+ signal
474
+ })
475
+ .then(async (response) => {
476
+ let jsonResponse = null;
477
+ try {
478
+ jsonResponse = await response.json();
479
+ }
480
+ catch (e) {
481
+ throw new DataConnectError(Code.OTHER, JSON.stringify(e));
482
+ }
483
+ if (response.status >= 400) {
484
+ logError('Error while performing request: ' + JSON.stringify(jsonResponse));
485
+ throw new DataConnectError(Code.OTHER, JSON.stringify(jsonResponse));
486
+ }
487
+ return jsonResponse;
488
+ })
489
+ .then(res => {
490
+ if (res.errors && res.errors.length) {
491
+ const stringified = JSON.stringify(res.errors);
492
+ logError('DataConnect error while performing request: ' + stringified);
493
+ throw new DataConnectError(Code.OTHER, stringified);
494
+ }
495
+ return res;
496
+ });
497
+ }
498
+
499
+ /**
500
+ * @license
501
+ * Copyright 2024 Google LLC
502
+ *
503
+ * Licensed under the Apache License, Version 2.0 (the "License");
504
+ * you may not use this file except in compliance with the License.
505
+ * You may obtain a copy of the License at
506
+ *
507
+ * http://www.apache.org/licenses/LICENSE-2.0
508
+ *
509
+ * Unless required by applicable law or agreed to in writing, software
510
+ * distributed under the License is distributed on an "AS IS" BASIS,
511
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
512
+ * See the License for the specific language governing permissions and
513
+ * limitations under the License.
514
+ */
515
+ class RESTTransport {
516
+ constructor(options, apiKey, authProvider, transportOptions) {
517
+ this.apiKey = apiKey;
518
+ this.authProvider = authProvider;
519
+ this.host = '';
520
+ this.location = 'l';
521
+ this.connectorName = '';
522
+ this.secure = true;
523
+ this.project = 'p';
524
+ this.accessToken = null;
525
+ this.authInitialized_ = false;
526
+ // TODO(mtewani): Update U to include shape of body defined in line 13.
527
+ this.invokeQuery = (queryName, body) => {
528
+ const abortController = new AbortController();
529
+ // TODO(mtewani): Update to proper value
530
+ const withAuth = this.getWithAuth().then(() => {
531
+ return dcFetch(addToken(`${this.endpointUrl}:executeQuery`, this.apiKey), {
532
+ name: `projects/${this.project}/locations/${this.location}/services/${this.serviceName}/connectors/${this.connectorName}`,
533
+ operationName: queryName,
534
+ variables: body
535
+ }, // TODO(mtewani): This is a patch, fix this.
536
+ abortController, this.accessToken);
537
+ });
538
+ return {
539
+ then: withAuth.then.bind(withAuth)
540
+ };
541
+ };
542
+ this.invokeMutation = (mutationName, body) => {
543
+ const abortController = new AbortController();
544
+ const taskResult = this.getWithAuth().then(() => {
545
+ return dcFetch(addToken(`${this.endpointUrl}:executeMutation`, this.apiKey), {
546
+ name: `projects/${this.project}/locations/${this.location}/services/${this.serviceName}/connectors/${this.connectorName}`,
547
+ operationName: mutationName,
548
+ variables: body
549
+ }, abortController, this.accessToken);
550
+ });
551
+ return {
552
+ then: taskResult.then.bind(taskResult),
553
+ // catch: taskResult.catch.bind(taskResult),
554
+ // finally: taskResult.finally.bind(taskResult),
555
+ cancel: () => abortController.abort()
556
+ };
557
+ };
558
+ if (transportOptions) {
559
+ if (typeof transportOptions.port === 'number') {
560
+ this.port = transportOptions.port;
561
+ }
562
+ if (typeof transportOptions.sslEnabled !== 'undefined') {
563
+ this.secure = transportOptions.sslEnabled;
564
+ }
565
+ this.host = transportOptions.host;
566
+ }
567
+ const { location, projectId: project, connector, service } = options;
568
+ if (location) {
569
+ this.location = location;
570
+ }
571
+ if (project) {
572
+ this.project = project;
573
+ }
574
+ this.serviceName = service;
575
+ if (!connector) {
576
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'Connector Name required!');
577
+ }
578
+ this.connectorName = connector;
579
+ }
580
+ get endpointUrl() {
581
+ return urlBuilder({
582
+ connector: this.connectorName,
583
+ location: this.location,
584
+ projectId: this.project,
585
+ service: this.serviceName
586
+ }, { host: this.host, sslEnabled: this.secure, port: this.port });
587
+ }
588
+ useEmulator(host, port, isSecure) {
589
+ this.host = host;
590
+ if (typeof port === 'number') {
591
+ this.port = port;
592
+ }
593
+ if (typeof isSecure !== 'undefined') {
594
+ this.secure = isSecure;
595
+ }
596
+ }
597
+ onTokenChanged(newToken) {
598
+ this.accessToken = newToken;
599
+ }
600
+ getWithAuth() {
601
+ let starterPromise = new Promise(resolve => resolve(this.accessToken));
602
+ if (!this.authInitialized_) {
603
+ if (this.authProvider) {
604
+ starterPromise = this.authProvider
605
+ .getToken(/*forceToken=*/ false)
606
+ .then(data => {
607
+ if (!data) {
608
+ return null;
609
+ }
610
+ this.accessToken = data.accessToken;
611
+ return this.accessToken;
612
+ });
613
+ }
614
+ else {
615
+ starterPromise = new Promise(resolve => resolve(''));
616
+ }
617
+ }
618
+ return starterPromise;
619
+ }
620
+ }
621
+
622
+ /**
623
+ * @license
624
+ * Copyright 2024 Google LLC
625
+ *
626
+ * Licensed under the Apache License, Version 2.0 (the "License");
627
+ * you may not use this file except in compliance with the License.
628
+ * You may obtain a copy of the License at
629
+ *
630
+ * http://www.apache.org/licenses/LICENSE-2.0
631
+ *
632
+ * Unless required by applicable law or agreed to in writing, software
633
+ * distributed under the License is distributed on an "AS IS" BASIS,
634
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
635
+ * See the License for the specific language governing permissions and
636
+ * limitations under the License.
637
+ */
638
+ function mutationRef(dcInstance, queryName, variables) {
639
+ dcInstance.setInitialized();
640
+ const ref = {
641
+ dataConnect: dcInstance,
642
+ name: queryName,
643
+ refType: MutationStr,
644
+ variables: variables
645
+ };
646
+ return ref;
647
+ }
648
+ class MutationManager {
649
+ constructor(transport) {
650
+ this.transport = transport;
651
+ this._inflight = [];
652
+ }
653
+ executeMutation(mutationRef) {
654
+ const result = this.transport.invokeMutation(mutationRef.name, mutationRef.variables);
655
+ const withRefPromise = result.then(res => {
656
+ const obj = Object.assign(Object.assign({}, res), { source: SOURCE_SERVER, ref: mutationRef, fetchTime: Date.now().toLocaleString() });
657
+ return obj;
658
+ });
659
+ this._inflight.push(result);
660
+ const removePromise = () => (this._inflight = this._inflight.filter(promise => promise !== result));
661
+ result.then(removePromise, removePromise);
662
+ return withRefPromise;
663
+ }
664
+ }
665
+ function executeMutation(mutationRef) {
666
+ return mutationRef.dataConnect._mutationManager.executeMutation(mutationRef);
667
+ }
668
+
669
+ /**
670
+ * @license
671
+ * Copyright 2024 Google LLC
672
+ *
673
+ * Licensed under the Apache License, Version 2.0 (the "License");
674
+ * you may not use this file except in compliance with the License.
675
+ * You may obtain a copy of the License at
676
+ *
677
+ * http://www.apache.org/licenses/LICENSE-2.0
678
+ *
679
+ * Unless required by applicable law or agreed to in writing, software
680
+ * distributed under the License is distributed on an "AS IS" BASIS,
681
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
682
+ * See the License for the specific language governing permissions and
683
+ * limitations under the License.
684
+ */
685
+ const FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR = 'FIREBASE_DATA_CONNECT_EMULATOR_HOST';
686
+ /**
687
+ *
688
+ * @param fullHost
689
+ * @returns TransportOptions
690
+ * @internal
691
+ */
692
+ function parseOptions(fullHost) {
693
+ const [protocol, hostName] = fullHost.split('://');
694
+ const isSecure = protocol === 'https';
695
+ const [host, portAsString] = hostName.split(':');
696
+ const port = Number(portAsString);
697
+ return { host, port, sslEnabled: isSecure };
698
+ }
699
+ class DataConnect {
700
+ constructor(app, dataConnectOptions, authProvider) {
701
+ this.app = app;
702
+ this.dataConnectOptions = dataConnectOptions;
703
+ this.authProvider = authProvider;
704
+ this.isEmulator = false;
705
+ this.initialized = false;
706
+ if (typeof process !== 'undefined' && process.env) {
707
+ const host = process.env[FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR];
708
+ if (host) {
709
+ logDebug('Found custom host. Using emulator');
710
+ this.isEmulator = true;
711
+ this.transportOptions = parseOptions(host);
712
+ }
713
+ }
714
+ }
715
+ _delete() {
716
+ _removeServiceInstance(this.app, 'data-connect', JSON.stringify(this.getSettings()));
717
+ return Promise.resolve();
718
+ }
719
+ getSettings() {
720
+ const copy = JSON.parse(JSON.stringify(this.dataConnectOptions));
721
+ delete copy.projectId;
722
+ return copy;
723
+ }
724
+ setInitialized() {
725
+ if (this.initialized) {
726
+ return;
727
+ }
728
+ if (this.transportClass === undefined) {
729
+ logDebug('transportClass not provided. Defaulting to RESTTransport.');
730
+ this.transportClass = RESTTransport;
731
+ }
732
+ if (this.authProvider) {
733
+ this.authTokenProvider = this.isEmulator
734
+ ? new EmulatorTokenProvider(EmulatorTokenProvider.OWNER)
735
+ : new FirebaseAuthProvider(this.app.name, this.app.options, this.authProvider);
736
+ this.authTokenProvider.addTokenChangeListener(token => {
737
+ logDebug(`New Token Available: ${token}`);
738
+ this._transport.onTokenChanged(token);
739
+ });
740
+ }
741
+ this.initialized = true;
742
+ this._transport = new this.transportClass(this.dataConnectOptions, this.app.options.apiKey, this.authTokenProvider);
743
+ if (this.transportOptions) {
744
+ this._transport.useEmulator(this.transportOptions.host, this.transportOptions.port, this.transportOptions.sslEnabled);
745
+ }
746
+ this._queryManager = new QueryManager(this._transport);
747
+ this._mutationManager = new MutationManager(this._transport);
748
+ }
749
+ enableEmulator(transportOptions) {
750
+ if (this.initialized) {
751
+ logError('enableEmulator called without initializing');
752
+ throw new DataConnectError(Code.ALREADY_INITIALIZED, 'DataConnect instance already initialized!');
753
+ }
754
+ this.transportOptions = transportOptions;
755
+ this.isEmulator = true;
756
+ }
757
+ }
758
+ function connectDataConnectEmulator(dc, host, port, sslEnabled = false) {
759
+ dc.enableEmulator({ host, port, sslEnabled });
760
+ }
761
+ function getDataConnect(appOrOptions, optionalOptions) {
762
+ let app;
763
+ let dcOptions;
764
+ if ('location' in appOrOptions) {
765
+ dcOptions = appOrOptions;
766
+ app = getApp();
767
+ }
768
+ else {
769
+ dcOptions = optionalOptions;
770
+ app = appOrOptions;
771
+ }
772
+ if (!app) {
773
+ app = getApp();
774
+ }
775
+ const provider = _getProvider(app, 'data-connect');
776
+ const identifier = JSON.stringify(dcOptions);
777
+ if (provider.isInitialized(identifier)) {
778
+ const dcInstance = provider.getImmediate({ identifier });
779
+ const options = provider.getOptions(identifier);
780
+ const optionsValid = Object.keys(options).length > 0;
781
+ if (optionsValid) {
782
+ logDebug('Re-using cached instance');
783
+ return dcInstance;
784
+ }
785
+ }
786
+ if (!dcOptions) {
787
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'DC Option Required');
788
+ }
789
+ logDebug('Creating new DataConnect instance');
790
+ // Initialize with options.
791
+ return provider.initialize({
792
+ instanceIdentifier: identifier,
793
+ options: dcOptions
794
+ });
795
+ }
796
+ function terminate(dataConnect) {
797
+ dataConnect._delete();
798
+ // TODO(mtewani): Stop pending tasks
799
+ }
800
+
801
+ /**
802
+ * @license
803
+ * Copyright 2024 Google LLC
804
+ *
805
+ * Licensed under the Apache License, Version 2.0 (the "License");
806
+ * you may not use this file except in compliance with the License.
807
+ * You may obtain a copy of the License at
808
+ *
809
+ * http://www.apache.org/licenses/LICENSE-2.0
810
+ *
811
+ * Unless required by applicable law or agreed to in writing, software
812
+ * distributed under the License is distributed on an "AS IS" BASIS,
813
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
814
+ * See the License for the specific language governing permissions and
815
+ * limitations under the License.
816
+ */
817
+ function registerDataConnect(variant) {
818
+ setSDKVersion(SDK_VERSION$1);
819
+ _registerComponent(new Component('data-connect', (container, { instanceIdentifier: settings, options }) => {
820
+ const app = container.getProvider('app').getImmediate();
821
+ const authProvider = container.getProvider('auth-internal');
822
+ let newOpts = options;
823
+ if (settings) {
824
+ newOpts = JSON.parse(settings);
825
+ }
826
+ return new DataConnect(app, Object.assign(Object.assign({}, newOpts), { projectId: app.options.projectId }), authProvider);
827
+ }, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
828
+ registerVersion(name, version, variant);
829
+ // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
830
+ registerVersion(name, version, 'esm2017');
831
+ }
832
+
833
+ /**
834
+ * @license
835
+ * Copyright 2024 Google LLC
836
+ *
837
+ * Licensed under the Apache License, Version 2.0 (the "License");
838
+ * you may not use this file except in compliance with the License.
839
+ * You may obtain a copy of the License at
840
+ *
841
+ * http://www.apache.org/licenses/LICENSE-2.0
842
+ *
843
+ * Unless required by applicable law or agreed to in writing, software
844
+ * distributed under the License is distributed on an "AS IS" BASIS,
845
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
846
+ * See the License for the specific language governing permissions and
847
+ * limitations under the License.
848
+ */
849
+ function executeQuery(queryRef) {
850
+ return queryRef.dataConnect._queryManager.executeQuery(queryRef);
851
+ }
852
+ function queryRef(dcInstance, queryName, variables, initialCache) {
853
+ dcInstance.setInitialized();
854
+ dcInstance._queryManager.track(queryName, variables, initialCache);
855
+ return {
856
+ dataConnect: dcInstance,
857
+ refType: QueryStr,
858
+ name: queryName,
859
+ variables: variables
860
+ };
861
+ }
862
+ function toQueryRef(serializedRef) {
863
+ const { refInfo: { name, variables, connectorConfig } } = serializedRef;
864
+ return queryRef(getDataConnect(connectorConfig), name, variables);
865
+ }
866
+
867
+ /**
868
+ * @license
869
+ * Copyright 2024 Google LLC
870
+ *
871
+ * Licensed under the Apache License, Version 2.0 (the "License");
872
+ * you may not use this file except in compliance with the License.
873
+ * You may obtain a copy of the License at
874
+ *
875
+ * http://www.apache.org/licenses/LICENSE-2.0
876
+ *
877
+ * Unless required by applicable law or agreed to in writing, software
878
+ * distributed under the License is distributed on an "AS IS" BASIS,
879
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
880
+ * See the License for the specific language governing permissions and
881
+ * limitations under the License.
882
+ */
883
+ function subscribe(queryRefOrSerializedResult, observerOrOnNext, onError, onComplete) {
884
+ let ref;
885
+ let initialCache;
886
+ if ('refInfo' in queryRefOrSerializedResult) {
887
+ let serializedRef = queryRefOrSerializedResult;
888
+ const { data, source, fetchTime } = serializedRef;
889
+ initialCache = {
890
+ data,
891
+ source,
892
+ fetchTime
893
+ };
894
+ ref = toQueryRef(serializedRef);
895
+ }
896
+ else {
897
+ ref = queryRefOrSerializedResult;
898
+ }
899
+ let onResult = undefined;
900
+ if (typeof observerOrOnNext === 'function') {
901
+ onResult = observerOrOnNext;
902
+ }
903
+ else {
904
+ onResult = observerOrOnNext.onNext;
905
+ onError = observerOrOnNext.onErr;
906
+ observerOrOnNext.onComplete;
907
+ }
908
+ if (!onResult) {
909
+ throw new DataConnectError(Code.INVALID_ARGUMENT, 'Must provide onNext');
910
+ }
911
+ return ref.dataConnect._queryManager.addSubscription(ref, onResult, onError, initialCache);
912
+ }
913
+
914
+ /**
915
+ * Firebase Data Connect
916
+ *
917
+ * @packageDocumentation
918
+ */
919
+ registerDataConnect();
920
+ // import { getDataConnect, queryRef } from './api';
921
+ // import { getApp } from '@firebase/app';
922
+ // const app = getApp();
923
+ // const dc = getDataConnect({ location: '', connector: '', serviceId: '', projectId: '' });
924
+ // interface Response {
925
+ // name: string;
926
+ // }
927
+ // const converter: Converter<Response> = {
928
+ // fromDataConnect(input: string) {
929
+ // return { name: input };
930
+ // },
931
+ // fromType(input) {
932
+ // return input;
933
+ // }
934
+ // };
935
+ // const myRef = queryRef(dc, '', converter);
936
+ // // Ref's shouldn't have access to their own cache, right?
937
+ // const a = execute(myRef);
938
+ // subscribe(myRef, (res) => {
939
+ // })
940
+
941
+ export { DataConnect, EmulatorTokenProvider, FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR, FirebaseAuthProvider, MutationManager, MutationStr, QueryStr, SOURCE_CACHE, SOURCE_SERVER, connectDataConnectEmulator, executeMutation, executeQuery, getDataConnect, mutationRef, parseOptions, queryRef, setLogLevel, subscribe, terminate, toQueryRef };
942
+ //# sourceMappingURL=index.esm2017.js.map