Kargi-Sitesi/node_modules/@firebase/data-connect/dist/node-esm/index.node.esm.js

1170 lines
43 KiB
JavaScript

import { FirebaseError } from '@firebase/util';
import { Logger } from '@firebase/logger';
import { _removeServiceInstance, getApp, _getProvider, _registerComponent, registerVersion, SDK_VERSION as SDK_VERSION$1 } from '@firebase/app';
import { Component } from '@firebase/component';
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const Code = {
OTHER: 'other',
ALREADY_INITIALIZED: 'already-initialized',
NOT_INITIALIZED: 'not-initialized',
NOT_SUPPORTED: 'not-supported',
INVALID_ARGUMENT: 'invalid-argument',
PARTIAL_ERROR: 'partial-error',
UNAUTHORIZED: 'unauthorized'
};
/** An error returned by a DataConnect operation. */
class DataConnectError extends FirebaseError {
/** @hideconstructor */
constructor(
/**
* The backend error code associated with this error.
*/
code,
/**
* A custom error description.
*/
message) {
super(code, message);
this.code = code;
this.message = message;
// HACK: We write a toString property directly because Error is not a real
// class and so inheritance does not work correctly. We could alternatively
// do the same "back-door inheritance" trick that FirebaseError does.
this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;
}
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** The semver (www.semver.org) version of the SDK. */
let SDK_VERSION = '';
/**
* SDK_VERSION should be set before any database instance is created
* @internal
*/
function setSDKVersion(version) {
SDK_VERSION = version;
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const logger = new Logger('@firebase/data-connect');
function setLogLevel(logLevel) {
logger.setLogLevel(logLevel);
}
function logDebug(msg) {
logger.debug(`DataConnect (${SDK_VERSION}): ${msg}`);
}
function logError(msg) {
logger.error(`DataConnect (${SDK_VERSION}): ${msg}`);
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let connectFetch = globalThis.fetch;
function initializeFetch(fetchImpl) {
connectFetch = fetchImpl;
}
function getGoogApiClientValue(_isUsingGen) {
let str = 'gl-js/ fire/' + SDK_VERSION;
if (_isUsingGen) {
str += ' js/gen';
}
return str;
}
function dcFetch(url, body, { signal }, appId, accessToken, appCheckToken, _isUsingGen) {
if (!connectFetch) {
throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!');
}
const headers = {
'Content-Type': 'application/json',
'X-Goog-Api-Client': getGoogApiClientValue(_isUsingGen)
};
if (accessToken) {
headers['X-Firebase-Auth-Token'] = accessToken;
}
if (appId) {
headers['x-firebase-gmpid'] = appId;
}
if (appCheckToken) {
headers['X-Firebase-AppCheck'] = appCheckToken;
}
const bodyStr = JSON.stringify(body);
logDebug(`Making request out to ${url} with body: ${bodyStr}`);
return connectFetch(url, {
body: bodyStr,
method: 'POST',
headers,
signal
})
.catch(err => {
throw new DataConnectError(Code.OTHER, 'Failed to fetch: ' + JSON.stringify(err));
})
.then(async (response) => {
let jsonResponse = null;
try {
jsonResponse = await response.json();
}
catch (e) {
throw new DataConnectError(Code.OTHER, JSON.stringify(e));
}
const message = getMessage(jsonResponse);
if (response.status >= 400) {
logError('Error while performing request: ' + JSON.stringify(jsonResponse));
if (response.status === 401) {
throw new DataConnectError(Code.UNAUTHORIZED, message);
}
throw new DataConnectError(Code.OTHER, message);
}
return jsonResponse;
})
.then(res => {
if (res.errors && res.errors.length) {
const stringified = JSON.stringify(res.errors);
logError('DataConnect error while performing request: ' + stringified);
throw new DataConnectError(Code.OTHER, stringified);
}
return res;
});
}
function getMessage(obj) {
if ('message' in obj) {
return obj.message;
}
return JSON.stringify(obj);
}
const name = "@firebase/data-connect";
const version = "0.1.1";
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @internal
* Abstraction around AppCheck's token fetching capabilities.
*/
class AppCheckTokenProvider {
constructor(appName_, appCheckProvider) {
this.appName_ = appName_;
this.appCheckProvider = appCheckProvider;
this.appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({ optional: true });
if (!this.appCheck) {
void (appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.get().then(appCheck => (this.appCheck = appCheck)).catch());
}
}
getToken(forceRefresh) {
if (!this.appCheck) {
return new Promise((resolve, reject) => {
// Support delayed initialization of FirebaseAppCheck. This allows our
// customers to initialize the RTDB SDK before initializing Firebase
// AppCheck and ensures that all requests are authenticated if a token
// becomes available before the timoeout below expires.
setTimeout(() => {
if (this.appCheck) {
this.getToken(forceRefresh).then(resolve, reject);
}
else {
resolve(null);
}
}, 0);
});
}
return this.appCheck.getToken(forceRefresh);
}
addTokenChangeListener(listener) {
var _a;
void ((_a = this.appCheckProvider) === null || _a === void 0 ? void 0 : _a.get().then(appCheck => appCheck.addTokenListener(listener)));
}
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @internal
class FirebaseAuthProvider {
constructor(_appName, _options, _authProvider) {
this._appName = _appName;
this._options = _options;
this._authProvider = _authProvider;
this._auth = _authProvider.getImmediate({ optional: true });
if (!this._auth) {
_authProvider.onInit(auth => (this._auth = auth));
}
}
getToken(forceRefresh) {
if (!this._auth) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (this._auth) {
this.getToken(forceRefresh).then(resolve, reject);
}
else {
resolve(null);
}
}, 0);
});
}
return this._auth.getToken(forceRefresh).catch(error => {
if (error && error.code === 'auth/token-not-initialized') {
logDebug('Got auth/token-not-initialized error. Treating as null token.');
return null;
}
else {
logError('Error received when attempting to retrieve token: ' +
JSON.stringify(error));
return Promise.reject(error);
}
});
}
addTokenChangeListener(listener) {
var _a;
(_a = this._auth) === null || _a === void 0 ? void 0 : _a.addAuthTokenListener(listener);
}
removeTokenChangeListener(listener) {
this._authProvider
.get()
.then(auth => auth.removeAuthTokenListener(listener))
.catch(err => logError(err));
}
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const QUERY_STR = 'query';
const MUTATION_STR = 'mutation';
const SOURCE_SERVER = 'SERVER';
const SOURCE_CACHE = 'CACHE';
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let encoderImpl;
function setEncoder(encoder) {
encoderImpl = encoder;
}
setEncoder(o => JSON.stringify(o));
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function setIfNotExists(map, key, val) {
if (!map.has(key)) {
map.set(key, val);
}
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function getRefSerializer(queryRef, data, source) {
return function toJSON() {
return {
data,
refInfo: {
name: queryRef.name,
variables: queryRef.variables,
connectorConfig: Object.assign({ projectId: queryRef.dataConnect.app.options.projectId }, queryRef.dataConnect.getSettings())
},
fetchTime: Date.now().toLocaleString(),
source
};
};
}
class QueryManager {
constructor(transport) {
this.transport = transport;
this._queries = new Map();
}
track(queryName, variables, initialCache) {
const ref = {
name: queryName,
variables,
refType: QUERY_STR
};
const key = encoderImpl(ref);
const newTrackedQuery = {
ref,
subscriptions: [],
currentCache: initialCache || null,
lastError: null
};
// @ts-ignore
setIfNotExists(this._queries, key, newTrackedQuery);
return this._queries.get(key);
}
addSubscription(queryRef, onResultCallback, onErrorCallback, initialCache) {
const key = encoderImpl({
name: queryRef.name,
variables: queryRef.variables,
refType: QUERY_STR
});
const trackedQuery = this._queries.get(key);
const subscription = {
userCallback: onResultCallback,
errCallback: onErrorCallback
};
const unsubscribe = () => {
const trackedQuery = this._queries.get(key);
trackedQuery.subscriptions = trackedQuery.subscriptions.filter(sub => sub !== subscription);
};
if (initialCache && trackedQuery.currentCache !== initialCache) {
logDebug('Initial cache found. Comparing dates.');
if (!trackedQuery.currentCache ||
(trackedQuery.currentCache &&
compareDates(trackedQuery.currentCache.fetchTime, initialCache.fetchTime))) {
trackedQuery.currentCache = initialCache;
}
}
if (trackedQuery.currentCache !== null) {
const cachedData = trackedQuery.currentCache.data;
onResultCallback({
data: cachedData,
source: SOURCE_CACHE,
ref: queryRef,
toJSON: getRefSerializer(queryRef, trackedQuery.currentCache.data, SOURCE_CACHE),
fetchTime: trackedQuery.currentCache.fetchTime
});
if (trackedQuery.lastError !== null && onErrorCallback) {
onErrorCallback(undefined);
}
}
trackedQuery.subscriptions.push({
userCallback: onResultCallback,
errCallback: onErrorCallback,
unsubscribe
});
if (!trackedQuery.currentCache) {
logDebug(`No cache available for query ${queryRef.name} with variables ${JSON.stringify(queryRef.variables)}. Calling executeQuery.`);
const promise = this.executeQuery(queryRef);
// We want to ignore the error and let subscriptions handle it
promise.then(undefined, err => { });
}
return unsubscribe;
}
executeQuery(queryRef) {
if (queryRef.refType !== QUERY_STR) {
throw new DataConnectError(Code.INVALID_ARGUMENT, `ExecuteQuery can only execute query operation`);
}
const key = encoderImpl({
name: queryRef.name,
variables: queryRef.variables,
refType: QUERY_STR
});
const trackedQuery = this._queries.get(key);
const result = this.transport.invokeQuery(queryRef.name, queryRef.variables);
const newR = result.then(res => {
const fetchTime = new Date().toString();
const result = Object.assign(Object.assign({}, res), { source: SOURCE_SERVER, ref: queryRef, toJSON: getRefSerializer(queryRef, res.data, SOURCE_SERVER), fetchTime });
trackedQuery.subscriptions.forEach(subscription => {
subscription.userCallback(result);
});
trackedQuery.currentCache = {
data: res.data,
source: SOURCE_CACHE,
fetchTime
};
return result;
}, err => {
trackedQuery.lastError = err;
trackedQuery.subscriptions.forEach(subscription => {
if (subscription.errCallback) {
subscription.errCallback(err);
}
});
throw err;
});
return newR;
}
enableEmulator(host, port) {
this.transport.useEmulator(host, port);
}
}
function compareDates(str1, str2) {
const date1 = new Date(str1);
const date2 = new Date(str2);
return date1.getTime() < date2.getTime();
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function urlBuilder(projectConfig, transportOptions) {
const { connector, location, projectId: project, service } = projectConfig;
const { host, sslEnabled, port } = transportOptions;
const protocol = sslEnabled ? 'https' : 'http';
const realHost = host || `firebasedataconnect.googleapis.com`;
let baseUrl = `${protocol}://${realHost}`;
if (typeof port === 'number') {
baseUrl += `:${port}`;
}
else if (typeof port !== 'undefined') {
logError('Port type is of an invalid type');
throw new DataConnectError(Code.INVALID_ARGUMENT, 'Incorrect type for port passed in!');
}
return `${baseUrl}/v1beta/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`;
}
function addToken(url, apiKey) {
if (!apiKey) {
return url;
}
const newUrl = new URL(url);
newUrl.searchParams.append('key', apiKey);
return newUrl.toString();
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class RESTTransport {
constructor(options, apiKey, appId, authProvider, appCheckProvider, transportOptions, _isUsingGen = false) {
var _a, _b;
this.apiKey = apiKey;
this.appId = appId;
this.authProvider = authProvider;
this.appCheckProvider = appCheckProvider;
this._isUsingGen = _isUsingGen;
this._host = '';
this._location = 'l';
this._connectorName = '';
this._secure = true;
this._project = 'p';
this._accessToken = null;
this._appCheckToken = null;
this._lastToken = null;
// TODO(mtewani): Update U to include shape of body defined in line 13.
this.invokeQuery = (queryName, body) => {
const abortController = new AbortController();
// TODO(mtewani): Update to proper value
const withAuth = this.withRetry(() => dcFetch(addToken(`${this.endpointUrl}:executeQuery`, this.apiKey), {
name: `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`,
operationName: queryName,
variables: body
}, // TODO(mtewani): This is a patch, fix this.
abortController, this.appId, this._accessToken, this._appCheckToken, this._isUsingGen));
return {
then: withAuth.then.bind(withAuth),
catch: withAuth.catch.bind(withAuth)
};
};
this.invokeMutation = (mutationName, body) => {
const abortController = new AbortController();
const taskResult = this.withRetry(() => {
return dcFetch(addToken(`${this.endpointUrl}:executeMutation`, this.apiKey), {
name: `projects/${this._project}/locations/${this._location}/services/${this._serviceName}/connectors/${this._connectorName}`,
operationName: mutationName,
variables: body
}, abortController, this.appId, this._accessToken, this._appCheckToken, this._isUsingGen);
});
return {
then: taskResult.then.bind(taskResult),
// catch: taskResult.catch.bind(taskResult),
// finally: taskResult.finally.bind(taskResult),
cancel: () => abortController.abort()
};
};
if (transportOptions) {
if (typeof transportOptions.port === 'number') {
this._port = transportOptions.port;
}
if (typeof transportOptions.sslEnabled !== 'undefined') {
this._secure = transportOptions.sslEnabled;
}
this._host = transportOptions.host;
}
const { location, projectId: project, connector, service } = options;
if (location) {
this._location = location;
}
if (project) {
this._project = project;
}
this._serviceName = service;
if (!connector) {
throw new DataConnectError(Code.INVALID_ARGUMENT, 'Connector Name required!');
}
this._connectorName = connector;
(_a = this.authProvider) === null || _a === void 0 ? void 0 : _a.addTokenChangeListener(token => {
logDebug(`New Token Available: ${token}`);
this._accessToken = token;
});
(_b = this.appCheckProvider) === null || _b === void 0 ? void 0 : _b.addTokenChangeListener(result => {
const { token } = result;
logDebug(`New App Check Token Available: ${token}`);
this._appCheckToken = token;
});
}
get endpointUrl() {
return urlBuilder({
connector: this._connectorName,
location: this._location,
projectId: this._project,
service: this._serviceName
}, { host: this._host, sslEnabled: this._secure, port: this._port });
}
useEmulator(host, port, isSecure) {
this._host = host;
if (typeof port === 'number') {
this._port = port;
}
if (typeof isSecure !== 'undefined') {
this._secure = isSecure;
}
}
onTokenChanged(newToken) {
this._accessToken = newToken;
}
async getWithAuth(forceToken = false) {
var _a;
let starterPromise = new Promise(resolve => resolve(this._accessToken));
if (this.appCheckProvider) {
this._appCheckToken = (_a = (await this.appCheckProvider.getToken())) === null || _a === void 0 ? void 0 : _a.token;
}
if (this.authProvider) {
starterPromise = this.authProvider
.getToken(/*forceToken=*/ forceToken)
.then(data => {
if (!data) {
return null;
}
this._accessToken = data.accessToken;
return this._accessToken;
});
}
else {
starterPromise = new Promise(resolve => resolve(''));
}
return starterPromise;
}
_setLastToken(lastToken) {
this._lastToken = lastToken;
}
withRetry(promiseFactory, retry = false) {
let isNewToken = false;
return this.getWithAuth(retry)
.then(res => {
isNewToken = this._lastToken !== res;
this._lastToken = res;
return res;
})
.then(promiseFactory)
.catch(err => {
// Only retry if the result is unauthorized and the last token isn't the same as the new one.
if ('code' in err &&
err.code === Code.UNAUTHORIZED &&
!retry &&
isNewToken) {
logDebug('Retrying due to unauthorized');
return this.withRetry(promiseFactory, true);
}
throw err;
});
}
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @param dcInstance Data Connect instance
* @param mutationName name of mutation
* @param variables variables to send with mutation
* @returns `MutationRef`
*/
function mutationRef(dcInstance, mutationName, variables) {
dcInstance.setInitialized();
const ref = {
dataConnect: dcInstance,
name: mutationName,
refType: MUTATION_STR,
variables: variables
};
return ref;
}
/**
* @internal
*/
class MutationManager {
constructor(_transport) {
this._transport = _transport;
this._inflight = [];
}
executeMutation(mutationRef) {
const result = this._transport.invokeMutation(mutationRef.name, mutationRef.variables);
const withRefPromise = result.then(res => {
const obj = Object.assign(Object.assign({}, res), { source: SOURCE_SERVER, ref: mutationRef, fetchTime: Date.now().toLocaleString() });
return obj;
});
this._inflight.push(result);
const removePromise = () => (this._inflight = this._inflight.filter(promise => promise !== result));
result.then(removePromise, removePromise);
return withRefPromise;
}
}
/**
* Execute Mutation
* @param mutationRef mutation to execute
* @returns `MutationRef`
*/
function executeMutation(mutationRef) {
return mutationRef.dataConnect._mutationManager.executeMutation(mutationRef);
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR = 'FIREBASE_DATA_CONNECT_EMULATOR_HOST';
/**
*
* @param fullHost
* @returns TransportOptions
* @internal
*/
function parseOptions(fullHost) {
const [protocol, hostName] = fullHost.split('://');
const isSecure = protocol === 'https';
const [host, portAsString] = hostName.split(':');
const port = Number(portAsString);
return { host, port, sslEnabled: isSecure };
}
/**
* Class representing Firebase Data Connect
*/
class DataConnect {
// @internal
constructor(app,
// TODO(mtewani): Replace with _dataConnectOptions in the future
dataConnectOptions, _authProvider, _appCheckProvider) {
this.app = app;
this.dataConnectOptions = dataConnectOptions;
this._authProvider = _authProvider;
this._appCheckProvider = _appCheckProvider;
this.isEmulator = false;
this._initialized = false;
this._isUsingGeneratedSdk = false;
if (typeof process !== 'undefined' && process.env) {
const host = process.env[FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR];
if (host) {
logDebug('Found custom host. Using emulator');
this.isEmulator = true;
this._transportOptions = parseOptions(host);
}
}
}
// @internal
_useGeneratedSdk() {
if (!this._isUsingGeneratedSdk) {
this._isUsingGeneratedSdk = true;
}
}
_delete() {
_removeServiceInstance(this.app, 'data-connect', JSON.stringify(this.getSettings()));
return Promise.resolve();
}
// @internal
getSettings() {
const copy = JSON.parse(JSON.stringify(this.dataConnectOptions));
delete copy.projectId;
return copy;
}
// @internal
setInitialized() {
if (this._initialized) {
return;
}
if (this._transportClass === undefined) {
logDebug('transportClass not provided. Defaulting to RESTTransport.');
this._transportClass = RESTTransport;
}
if (this._authProvider) {
this._authTokenProvider = new FirebaseAuthProvider(this.app.name, this.app.options, this._authProvider);
}
if (this._appCheckProvider) {
this._appCheckTokenProvider = new AppCheckTokenProvider(this.app.name, this._appCheckProvider);
}
this._initialized = true;
this._transport = new this._transportClass(this.dataConnectOptions, this.app.options.apiKey, this.app.options.appId, this._authTokenProvider, this._appCheckTokenProvider, undefined, this._isUsingGeneratedSdk);
if (this._transportOptions) {
this._transport.useEmulator(this._transportOptions.host, this._transportOptions.port, this._transportOptions.sslEnabled);
}
this._queryManager = new QueryManager(this._transport);
this._mutationManager = new MutationManager(this._transport);
}
// @internal
enableEmulator(transportOptions) {
if (this._initialized) {
logError('enableEmulator called after initialization');
throw new DataConnectError(Code.ALREADY_INITIALIZED, 'DataConnect instance already initialized!');
}
this._transportOptions = transportOptions;
this.isEmulator = true;
}
}
/**
* Connect to the DataConnect Emulator
* @param dc Data Connect instance
* @param host host of emulator server
* @param port port of emulator server
* @param sslEnabled use https
*/
function connectDataConnectEmulator(dc, host, port, sslEnabled = false) {
dc.enableEmulator({ host, port, sslEnabled });
}
function getDataConnect(appOrOptions, optionalOptions) {
let app;
let dcOptions;
if ('location' in appOrOptions) {
dcOptions = appOrOptions;
app = getApp();
}
else {
dcOptions = optionalOptions;
app = appOrOptions;
}
if (!app || Object.keys(app).length === 0) {
app = getApp();
}
const provider = _getProvider(app, 'data-connect');
const identifier = JSON.stringify(dcOptions);
if (provider.isInitialized(identifier)) {
const dcInstance = provider.getImmediate({ identifier });
const options = provider.getOptions(identifier);
const optionsValid = Object.keys(options).length > 0;
if (optionsValid) {
logDebug('Re-using cached instance');
return dcInstance;
}
}
validateDCOptions(dcOptions);
logDebug('Creating new DataConnect instance');
// Initialize with options.
return provider.initialize({
instanceIdentifier: identifier,
options: dcOptions
});
}
/**
*
* @param dcOptions
* @returns {void}
* @internal
*/
function validateDCOptions(dcOptions) {
const fields = ['connector', 'location', 'service'];
if (!dcOptions) {
throw new DataConnectError(Code.INVALID_ARGUMENT, 'DC Option Required');
}
fields.forEach(field => {
if (dcOptions[field] === null || dcOptions[field] === undefined) {
throw new DataConnectError(Code.INVALID_ARGUMENT, `${field} Required`);
}
});
return true;
}
/**
* Delete DataConnect instance
* @param dataConnect DataConnect instance
* @returns
*/
function terminate(dataConnect) {
return dataConnect._delete();
// TODO(mtewani): Stop pending tasks
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function registerDataConnect(variant) {
setSDKVersion(SDK_VERSION$1);
_registerComponent(new Component('data-connect', (container, { instanceIdentifier: settings, options }) => {
const app = container.getProvider('app').getImmediate();
const authProvider = container.getProvider('auth-internal');
const appCheckProvider = container.getProvider('app-check-internal');
let newOpts = options;
if (settings) {
newOpts = JSON.parse(settings);
}
if (!app.options.projectId) {
throw new DataConnectError(Code.INVALID_ARGUMENT, 'Project ID must be provided. Did you pass in a proper projectId to initializeApp?');
}
return new DataConnect(app, Object.assign(Object.assign({}, newOpts), { projectId: app.options.projectId }), authProvider, appCheckProvider);
}, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
registerVersion(name, version, variant);
// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
registerVersion(name, version, 'esm2017');
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Execute Query
* @param queryRef query to execute.
* @returns `QueryPromise`
*/
function executeQuery(queryRef) {
return queryRef.dataConnect._queryManager.executeQuery(queryRef);
}
/**
* Execute Query
* @param dcInstance Data Connect instance to use.
* @param queryName Query to execute
* @param variables Variables to execute with
* @param initialCache initial cache to use for client hydration
* @returns `QueryRef`
*/
function queryRef(dcInstance, queryName, variables, initialCache) {
dcInstance.setInitialized();
dcInstance._queryManager.track(queryName, variables, initialCache);
return {
dataConnect: dcInstance,
refType: QUERY_STR,
name: queryName,
variables: variables
};
}
/**
* Converts serialized ref to query ref
* @param serializedRef ref to convert to `QueryRef`
* @returns `QueryRef`
*/
function toQueryRef(serializedRef) {
const { refInfo: { name, variables, connectorConfig } } = serializedRef;
return queryRef(getDataConnect(connectorConfig), name, variables);
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The generated SDK will allow the user to pass in either the variable or the data connect instance with the variable,
* and this function validates the variables and returns back the DataConnect instance and variables based on the arguments passed in.
* @param connectorConfig
* @param dcOrVars
* @param vars
* @param validateVars
* @returns {DataConnect} and {Variables} instance
* @internal
*/
function validateArgs(connectorConfig, dcOrVars, vars, validateVars) {
let dcInstance;
let realVars;
if (dcOrVars && 'enableEmulator' in dcOrVars) {
dcInstance = dcOrVars;
realVars = vars;
}
else {
dcInstance = getDataConnect(connectorConfig);
realVars = dcOrVars;
}
if (!dcInstance || (!realVars && validateVars)) {
throw new DataConnectError(Code.INVALID_ARGUMENT, 'Variables required.');
}
return { dc: dcInstance, vars: realVars };
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Subscribe to a `QueryRef`
* @param queryRefOrSerializedResult query ref or serialized result.
* @param observerOrOnNext observer object or next function.
* @param onError Callback to call when error gets thrown.
* @param onComplete Called when subscription completes.
* @returns `SubscriptionOptions`
*/
function subscribe(queryRefOrSerializedResult, observerOrOnNext, onError, onComplete) {
let ref;
let initialCache;
if ('refInfo' in queryRefOrSerializedResult) {
const serializedRef = queryRefOrSerializedResult;
const { data, source, fetchTime } = serializedRef;
initialCache = {
data,
source,
fetchTime
};
ref = toQueryRef(serializedRef);
}
else {
ref = queryRefOrSerializedResult;
}
let onResult = undefined;
if (typeof observerOrOnNext === 'function') {
onResult = observerOrOnNext;
}
else {
onResult = observerOrOnNext.onNext;
onError = observerOrOnNext.onErr;
observerOrOnNext.onComplete;
}
if (!onResult) {
throw new DataConnectError(Code.INVALID_ARGUMENT, 'Must provide onNext');
}
return ref.dataConnect._queryManager.addSubscription(ref, onResult, onError, initialCache);
}
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
initializeFetch(fetch);
registerDataConnect('node');
export { DataConnect, MUTATION_STR, MutationManager, QUERY_STR, SOURCE_CACHE, SOURCE_SERVER, connectDataConnectEmulator, executeMutation, executeQuery, getDataConnect, mutationRef, parseOptions, queryRef, setLogLevel, subscribe, terminate, toQueryRef, validateArgs, validateDCOptions };
//# sourceMappingURL=index.node.esm.js.map