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