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