Skip to content

Commit c24ecf3

Browse files
authored
Address version conflict when used together with firebase-admin (#1916)
* abstract SDK_VERSION * some comment * remove the unnecessary build target * require default * [AUTOMATED]: Prettier Code Styling * [AUTOMATED]: License Headers * remove experimental changes * remove unused var * only ignore MODULE_NOT_FOUND error * [AUTOMATED]: Prettier Code Styling * revert module export change
1 parent 2348a25 commit c24ecf3

File tree

5 files changed

+63
-28
lines changed

5 files changed

+63
-28
lines changed

packages/database/index.node.ts

+26-15
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import firebase from '@firebase/app';
19-
import { CONSTANTS, isNodeSdk } from '@firebase/util';
20-
import { FirebaseApp, FirebaseNamespace } from '@firebase/app-types';
18+
import { FirebaseNamespace, FirebaseApp } from '@firebase/app-types';
2119
import { _FirebaseNamespace } from '@firebase/app-types/private';
2220
import { Database } from './src/api/Database';
2321
import { DataSnapshot } from './src/api/DataSnapshot';
@@ -29,30 +27,26 @@ import * as INTERNAL from './src/api/internal';
2927
import * as TEST_ACCESS from './src/api/test_access';
3028
import './src/nodePatches';
3129
import * as types from '@firebase/database-types';
30+
import { setSDKVersion } from './src/core/version';
31+
import { CONSTANTS, isNodeSdk } from '@firebase/util';
32+
33+
const ServerValue = Database.ServerValue;
3234

3335
/**
3436
* A one off register function which returns a database based on the app and
3537
* passed database URL.
3638
*
3739
* @param app A valid FirebaseApp-like object
3840
* @param url A valid Firebase databaseURL
41+
* @param version custom version e.g. firebase-admin version
3942
*/
40-
41-
const ServerValue = Database.ServerValue;
42-
43-
export function initStandalone(
44-
app: FirebaseApp,
45-
url: string,
46-
version?: string
47-
) {
43+
export function initStandalone(app: FirebaseApp, url: string, version: string) {
4844
/**
4945
* This should allow the firebase-admin package to provide a custom version
5046
* to the backend
5147
*/
5248
CONSTANTS.NODE_ADMIN = true;
53-
if (version) {
54-
firebase.SDK_VERSION = version;
55-
}
49+
setSDKVersion(version);
5650

5751
return {
5852
instance: RepoManager.getInstance().databaseFromApp(app, url),
@@ -70,6 +64,9 @@ export function initStandalone(
7064
}
7165

7266
export function registerDatabase(instance: FirebaseNamespace) {
67+
// set SDK_VERSION
68+
setSDKVersion(instance.SDK_VERSION);
69+
7370
// Register the Database Service with the 'firebase' namespace.
7471
const namespace = (instance as _FirebaseNamespace).INTERNAL.registerService(
7572
'database',
@@ -94,7 +91,21 @@ export function registerDatabase(instance: FirebaseNamespace) {
9491
}
9592
}
9693

97-
registerDatabase(firebase);
94+
try {
95+
// If @firebase/app is not present, skip registering database.
96+
// It could happen when this package is used in firebase-admin which doesn't depend on @firebase/app.
97+
// Previously firebase-admin depends on @firebase/app, which causes version conflict on
98+
// @firebase/app when used together with the js sdk. More detail:
99+
// https://github.com/firebase/firebase-js-sdk/issues/1696#issuecomment-501546596
100+
const firebase = require('@firebase/app').default;
101+
registerDatabase(firebase);
102+
} catch (err) {
103+
// catch and ignore 'MODULE_NOT_FOUND' error in firebase-admin context
104+
// we can safely ignore this error because RTDB in firebase-admin works without @firebase/app
105+
if (err.code !== 'MODULE_NOT_FOUND') {
106+
throw err;
107+
}
108+
}
98109

99110
// Types to export for the admin SDK
100111
export { Database, Query, Reference, enableLogging, ServerValue };

packages/database/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
import firebase from '@firebase/app';
19-
import { FirebaseApp, FirebaseNamespace } from '@firebase/app-types';
19+
import { FirebaseNamespace } from '@firebase/app-types';
2020
import { _FirebaseNamespace } from '@firebase/app-types/private';
2121
import { Database } from './src/api/Database';
2222
import { DataSnapshot } from './src/api/DataSnapshot';
@@ -28,10 +28,14 @@ import * as INTERNAL from './src/api/internal';
2828
import * as TEST_ACCESS from './src/api/test_access';
2929
import { isNodeSdk } from '@firebase/util';
3030
import * as types from '@firebase/database-types';
31+
import { setSDKVersion } from './src/core/version';
3132

3233
const ServerValue = Database.ServerValue;
3334

3435
export function registerDatabase(instance: FirebaseNamespace) {
36+
// set SDK_VERSION
37+
setSDKVersion(instance.SDK_VERSION);
38+
3539
// Register the Database Service with the 'firebase' namespace.
3640
const namespace = (instance as _FirebaseNamespace).INTERNAL.registerService(
3741
'database',

packages/database/src/core/PersistentConnection.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import firebase from '@firebase/app';
19-
import { contains, isEmpty, safeGet } from '@firebase/util';
18+
import { contains, isEmpty, safeGet, CONSTANTS } from '@firebase/util';
2019
import { stringify } from '@firebase/util';
2120
import { assert } from '@firebase/util';
2221
import { error, log, logWrapper, warn, ObjectToUniqueKey } from './util/util';
@@ -25,12 +24,12 @@ import { VisibilityMonitor } from './util/VisibilityMonitor';
2524
import { OnlineMonitor } from './util/OnlineMonitor';
2625
import { isAdmin, isValidFormat } from '@firebase/util';
2726
import { Connection } from '../realtime/Connection';
28-
import { CONSTANTS } from '@firebase/util';
2927
import { isMobileCordova, isReactNative, isNodeSdk } from '@firebase/util';
3028
import { ServerActions } from './ServerActions';
3129
import { AuthTokenProvider } from './AuthTokenProvider';
3230
import { RepoInfo } from './RepoInfo';
3331
import { Query } from '../api/Query';
32+
import { SDK_VERSION } from './version';
3433

3534
const RECONNECT_MIN_DELAY = 1000;
3635
const RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000; // 5 minutes in milliseconds (Case: 1858)
@@ -926,9 +925,7 @@ export class PersistentConnection extends ServerActions {
926925
clientName = 'node';
927926
}
928927

929-
stats[
930-
'sdk.' + clientName + '.' + firebase.SDK_VERSION.replace(/\./g, '-')
931-
] = 1;
928+
stats['sdk.' + clientName + '.' + SDK_VERSION.replace(/\./g, '-')] = 1;
932929

933930
if (isMobileCordova()) {
934931
stats['framework.cordova'] = 1;

packages/database/src/core/version.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/** The semver (www.semver.org) version of the SDK. */
19+
export let SDK_VERSION = '';
20+
21+
// SDK_VERSION should be set before any database instance is created
22+
export function setSDKVersion(version: string): void {
23+
SDK_VERSION = version;
24+
}

packages/database/src/realtime/WebSocketConnection.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ import { RepoInfo } from '../core/RepoInfo';
1919

2020
declare const MozWebSocket: any;
2121

22-
import firebase from '@firebase/app';
23-
import { assert } from '@firebase/util';
22+
import { assert, CONSTANTS as ENV_CONSTANTS } from '@firebase/util';
2423
import { logWrapper, splitStringBySize } from '../core/util/util';
2524
import { StatsManager } from '../core/stats/StatsManager';
2625
import {
@@ -33,12 +32,12 @@ import {
3332
VERSION_PARAM,
3433
WEBSOCKET
3534
} from './Constants';
36-
import { CONSTANTS as ENV_CONSTANTS } from '@firebase/util';
3735
import { PersistentStorage } from '../core/storage/storage';
3836
import { jsonEval, stringify } from '@firebase/util';
3937
import { isNodeSdk } from '@firebase/util';
4038
import { Transport } from './Transport';
4139
import { StatsCollection } from '../core/stats/StatsCollection';
40+
import { SDK_VERSION } from '../core/version';
4241

4342
const WEBSOCKET_MAX_FRAME_SIZE = 16384;
4443
const WEBSOCKET_KEEPALIVE_INTERVAL = 45000;
@@ -150,9 +149,9 @@ export class WebSocketConnection implements Transport {
150149
// UA Format: Firebase/<wire_protocol>/<sdk_version>/<platform>/<device>
151150
const options: { [k: string]: object } = {
152151
headers: {
153-
'User-Agent': `Firebase/${PROTOCOL_VERSION}/${
154-
firebase.SDK_VERSION
155-
}/${process.platform}/${device}`
152+
'User-Agent': `Firebase/${PROTOCOL_VERSION}/${SDK_VERSION}/${
153+
process.platform
154+
}/${device}`
156155
}
157156
};
158157

0 commit comments

Comments
 (0)