Skip to content

Commit dfe65ff

Browse files
authoredSep 24, 2021
Share code with Admin SDK properly (#5537)
* Add standalone entry point in database-compat * add exports field * fix lint * Create afraid-boxes-roll.md * address comments * add an emptry line to the end of file
1 parent e62d02e commit dfe65ff

12 files changed

+276
-165
lines changed
 

‎.changeset/afraid-boxes-roll.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@firebase/database-compat": patch
3+
"@firebase/database": patch
4+
---
5+
6+
Added an entry point `@firebase/database-compat/standalone` to share code with Admin SDK properly

‎packages/database-compat/package.json

+13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@
99
"esm5": "dist/index.esm5.js",
1010
"license": "Apache-2.0",
1111
"typings": "dist/database-compat/src/index.d.ts",
12+
"files": [
13+
"dist",
14+
"standalone/package.json"
15+
],
16+
"exports": {
17+
".": {
18+
"node": "./dist/index.js",
19+
"default": "./dist/index.esm2017.js"
20+
},
21+
"./standalone": {
22+
"node": "./dist/index.standalone.js"
23+
}
24+
},
1225
"scripts": {
1326
"lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'",
1427
"lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'",

‎packages/database-compat/rollup.config.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818
import json from '@rollup/plugin-json';
1919
import typescriptPlugin from 'rollup-plugin-typescript2';
2020
import typescript from 'typescript';
21+
import commonjs from '@rollup/plugin-commonjs';
22+
import resolveModule from '@rollup/plugin-node-resolve';
2123

2224
import pkg from './package.json';
25+
import standalonePkg from './standalone/package.json';
2326

24-
const deps = Object.keys(
25-
Object.assign({}, pkg.peerDependencies, pkg.dependencies)
26-
);
27+
const deps = Object.keys({ ...pkg.peerDependencies, ...pkg.dependencies });
2728

2829
function onWarn(warning, defaultWarn) {
2930
if (warning.code === 'CIRCULAR_DEPENDENCY') {
@@ -81,6 +82,33 @@ const es5Builds = [
8182
},
8283
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)),
8384
onwarn: onWarn
85+
},
86+
/**
87+
* Standalone Build (used by Admin SDK).
88+
* @firebase/database and only @firebase/database is bundled in this build.
89+
*/
90+
{
91+
input: 'src/index.standalone.ts',
92+
output: [
93+
{
94+
file: standalonePkg.main.replace('../', ''),
95+
format: 'cjs',
96+
sourcemap: true
97+
}
98+
],
99+
plugins: [
100+
...es5BuildPlugins,
101+
resolveModule({
102+
mainFields: ['standalone'],
103+
preferBuiltins: true
104+
}),
105+
commonjs()
106+
],
107+
treeshake: {
108+
moduleSideEffects: false
109+
},
110+
external: id => deps.filter(dep => dep !== '@firebase/database').some(dep => id === dep || id.startsWith(`${dep}/`)),
111+
onwarn: onWarn
84112
}
85113
];
86114

‎packages/database-compat/src/index.node.ts

+5-68
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
18-
import { FirebaseApp, FirebaseNamespace } from '@firebase/app-types';
17+
import firebase from '@firebase/app-compat';
18+
import { FirebaseNamespace } from '@firebase/app-types';
1919
import { _FirebaseNamespace } from '@firebase/app-types/private';
20-
import { FirebaseAuthInternal } from '@firebase/auth-interop-types';
2120
import { Component, ComponentType } from '@firebase/component';
2221
import { enableLogging } from '@firebase/database';
2322
import * as types from '@firebase/database-types';
24-
import { CONSTANTS, isNodeSdk } from '@firebase/util';
2523

2624
import { name, version } from '../package.json';
2725
import { Database } from '../src/api/Database';
@@ -30,45 +28,9 @@ import { DataSnapshot, Query, Reference } from '../src/api/Reference';
3028

3129
const ServerValue = Database.ServerValue;
3230

33-
/**
34-
* A one off register function which returns a database based on the app and
35-
* passed database URL. (Used by the Admin SDK)
36-
*
37-
* @param app - A valid FirebaseApp-like object
38-
* @param url - A valid Firebase databaseURL
39-
* @param version - custom version e.g. firebase-admin version
40-
* @param nodeAdmin - true if the SDK is being initialized from Firebase Admin.
41-
*/
42-
export function initStandalone(
43-
app: FirebaseApp,
44-
url: string,
45-
version: string,
46-
nodeAdmin = true
47-
) {
48-
CONSTANTS.NODE_ADMIN = nodeAdmin;
49-
return INTERNAL.initStandalone({
50-
app,
51-
url,
52-
version,
53-
// firebase-admin-node's app.INTERNAL implements FirebaseAuthInternal interface
54-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
55-
customAuthImpl: (app as any).INTERNAL as FirebaseAuthInternal,
56-
namespace: {
57-
Reference,
58-
Query,
59-
Database,
60-
DataSnapshot,
61-
enableLogging,
62-
INTERNAL,
63-
ServerValue
64-
},
65-
nodeAdmin
66-
});
67-
}
68-
69-
export function registerDatabase(instance: FirebaseNamespace) {
31+
function registerDatabase(instance: FirebaseNamespace) {
7032
// Register the Database Service with the 'firebase' namespace.
71-
const namespace = (instance as _FirebaseNamespace).INTERNAL.registerComponent(
33+
(instance as _FirebaseNamespace).INTERNAL.registerComponent(
7234
new Component(
7335
'database-compat',
7436
(container, { instanceIdentifier: url }) => {
@@ -98,33 +60,9 @@ export function registerDatabase(instance: FirebaseNamespace) {
9860
);
9961

10062
instance.registerVersion(name, version, 'node');
101-
102-
if (isNodeSdk()) {
103-
module.exports = Object.assign({}, namespace, { initStandalone });
104-
}
105-
}
106-
107-
try {
108-
// If @firebase/app is not present, skip registering database.
109-
// It could happen when this package is used in firebase-admin which doesn't depend on @firebase/app.
110-
// Previously firebase-admin depends on @firebase/app, which causes version conflict on
111-
// @firebase/app when used together with the js sdk. More detail:
112-
// https://github.com/firebase/firebase-js-sdk/issues/1696#issuecomment-501546596
113-
// eslint-disable-next-line import/no-extraneous-dependencies, @typescript-eslint/no-require-imports
114-
const firebase = require('@firebase/app-compat').default;
115-
registerDatabase(firebase);
116-
} catch (err) {
117-
// catch and ignore 'MODULE_NOT_FOUND' error in firebase-admin context
118-
// we can safely ignore this error because RTDB in firebase-admin works without @firebase/app
119-
if (err.code !== 'MODULE_NOT_FOUND') {
120-
throw err;
121-
}
12263
}
12364

124-
// Types to export for the admin SDK
125-
export { Database, Query, Reference, enableLogging, ServerValue };
126-
127-
export { OnDisconnect } from '@firebase/database';
65+
registerDatabase(firebase);
12866

12967
declare module '@firebase/app-compat' {
13068
interface FirebaseNamespace {
@@ -139,4 +77,3 @@ declare module '@firebase/app-compat' {
13977
database?(): types.FirebaseDatabase;
14078
}
14179
}
142-
export { DataSnapshot } from '../src/api/Reference';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
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+
import { FirebaseApp } from '@firebase/app-types';
19+
import { FirebaseAuthInternal } from '@firebase/auth-interop-types';
20+
import { enableLogging } from '@firebase/database';
21+
import { CONSTANTS } from '@firebase/util';
22+
23+
import { Database } from './api/Database';
24+
import * as INTERNAL from './api/internal';
25+
import { DataSnapshot, Query, Reference } from './api/Reference';
26+
27+
const ServerValue = Database.ServerValue;
28+
29+
/**
30+
* A one off register function which returns a database based on the app and
31+
* passed database URL. (Used by the Admin SDK)
32+
*
33+
* @param app - A valid FirebaseApp-like object
34+
* @param url - A valid Firebase databaseURL
35+
* @param version - custom version e.g. firebase-admin version
36+
* @param nodeAdmin - true if the SDK is being initialized from Firebase Admin.
37+
*/
38+
export function initStandalone(
39+
app: FirebaseApp,
40+
url: string,
41+
version: string,
42+
nodeAdmin = true
43+
) {
44+
CONSTANTS.NODE_ADMIN = nodeAdmin;
45+
return INTERNAL.initStandalone({
46+
app,
47+
url,
48+
version,
49+
// firebase-admin-node's app.INTERNAL implements FirebaseAuthInternal interface
50+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
51+
customAuthImpl: (app as any).INTERNAL as FirebaseAuthInternal,
52+
namespace: {
53+
Reference,
54+
Query,
55+
Database,
56+
DataSnapshot,
57+
enableLogging,
58+
INTERNAL,
59+
ServerValue
60+
},
61+
nodeAdmin
62+
});
63+
}
64+
65+
// Types to export for the admin SDK
66+
export { Database, Query, Reference, enableLogging, ServerValue };
67+
export { OnDisconnect } from '@firebase/database';
68+
export { DataSnapshot } from './api/Reference';

‎packages/database-compat/src/index.ts

+8-14
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ import { enableLogging } from '@firebase/database';
2323
import * as types from '@firebase/database-types';
2424

2525
import { name, version } from '../package.json';
26-
import { Database as DatabaseCompat } from '../src/api/Database';
26+
import { Database } from '../src/api/Database';
2727
import * as INTERNAL from '../src/api/internal';
28-
// rename the imports to avoid conflicts with imports that will be added by "yarn add-compat-overloads" during a release build
29-
import { DataSnapshot as DataSnapshotCompat, Query as QueryCompat, Reference } from '../src/api/Reference';
28+
import { DataSnapshot, Query, Reference } from '../src/api/Reference';
3029

31-
const ServerValue = DatabaseCompat.ServerValue;
30+
const ServerValue = Database.ServerValue;
3231

3332
export function registerDatabase(instance: FirebaseNamespace) {
3433
// Register the Database Service with the 'firebase' namespace.
35-
const namespace = (
34+
(
3635
instance as unknown as _FirebaseNamespace
3736
).INTERNAL.registerComponent(
3837
new Component(
@@ -44,17 +43,17 @@ export function registerDatabase(instance: FirebaseNamespace) {
4443
const databaseExp = container
4544
.getProvider('database')
4645
.getImmediate({ identifier: url });
47-
return new DatabaseCompat(databaseExp, app);
46+
return new Database(databaseExp, app);
4847
},
4948
ComponentType.PUBLIC
5049
)
5150
.setServiceProps(
5251
// firebase.database namespace properties
5352
{
5453
Reference,
55-
Query: QueryCompat,
56-
Database: DatabaseCompat,
57-
DataSnapshot: DataSnapshotCompat,
54+
Query,
55+
Database,
56+
DataSnapshot,
5857
enableLogging,
5958
INTERNAL,
6059
ServerValue
@@ -68,11 +67,6 @@ export function registerDatabase(instance: FirebaseNamespace) {
6867

6968
registerDatabase(firebase);
7069

71-
// Types to export for the admin SDK. They are exported here in the browser entry point only for types
72-
// The same symbol should be exported from the node entry point so their values can be accessed at runtime by admin SDK
73-
export { DatabaseCompat as Database, QueryCompat as Query, Reference, enableLogging, ServerValue, DataSnapshotCompat as DataSnapshot };
74-
export { OnDisconnect } from '@firebase/database';
75-
7670
declare module '@firebase/app-compat' {
7771
interface FirebaseNamespace {
7872
database?: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "@firebase/database-compat/standalone",
3+
"description": "The entry point for sharing code with Admin SDK",
4+
"main": "../dist/index.standalone.js",
5+
"typings": "../dist/database-compat/src/index.standalone.d.ts",
6+
"private": true
7+
}

‎packages/database/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"browser": "dist/index.esm2017.js",
88
"module": "dist/index.esm2017.js",
99
"esm5": "dist/index.esm5.js",
10+
"standalone": "dist/index.standalone.js",
1011
"files": [
1112
"dist"
1213
],

‎packages/database/rollup.config.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,20 @@ const es5Builds = [
7575
},
7676
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)),
7777
onwarn: onWarn
78-
}
78+
},
79+
/**
80+
* Standalone Build
81+
*/
82+
{
83+
input: 'src/index.standalone.ts',
84+
output: [{ file: pkg.standalone, format: 'cjs', sourcemap: true }],
85+
plugins: es5BuildPlugins,
86+
treeshake: {
87+
moduleSideEffects: false
88+
},
89+
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)),
90+
onwarn: onWarn
91+
},
7992
];
8093

8194
/**
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
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+
// APIs that don't depend on @firebase/app
19+
export {
20+
Database,
21+
EmulatorMockTokenOptions,
22+
enableLogging,
23+
goOffline,
24+
goOnline,
25+
connectDatabaseEmulator
26+
} from './api/Database';
27+
export {
28+
Query,
29+
DatabaseReference,
30+
ListenOptions,
31+
Unsubscribe,
32+
ThenableReference
33+
} from './api/Reference';
34+
export { OnDisconnect } from './api/OnDisconnect';
35+
export {
36+
DataSnapshot,
37+
EventType,
38+
QueryConstraint,
39+
QueryConstraintType,
40+
endAt,
41+
endBefore,
42+
equalTo,
43+
get,
44+
limitToFirst,
45+
limitToLast,
46+
off,
47+
onChildAdded,
48+
onChildChanged,
49+
onChildMoved,
50+
onChildRemoved,
51+
onDisconnect,
52+
onValue,
53+
orderByChild,
54+
orderByKey,
55+
orderByPriority,
56+
orderByValue,
57+
push,
58+
query,
59+
ref,
60+
refFromURL,
61+
remove,
62+
set,
63+
setPriority,
64+
setWithPriority,
65+
startAfter,
66+
startAt,
67+
update,
68+
child
69+
} from './api/Reference_impl';
70+
export { increment, serverTimestamp } from './api/ServerValue';
71+
export {
72+
runTransaction,
73+
TransactionOptions,
74+
TransactionResult
75+
} from './api/Transaction';
76+
77+
// internal exports
78+
export { setSDKVersion as _setSDKVersion } from './core/version';
79+
export {
80+
ReferenceImpl as _ReferenceImpl,
81+
QueryImpl as _QueryImpl
82+
} from './api/Reference_impl';
83+
export { repoManagerDatabaseFromApp as _repoManagerDatabaseFromApp } from './api/Database';
84+
export {
85+
validatePathString as _validatePathString,
86+
validateWritablePath as _validateWritablePath
87+
} from './core/util/validation';
88+
export { UserCallback as _UserCallback } from './core/view/EventRegistration';
89+
export { QueryParams as _QueryParams } from './core/view/QueryParams';
90+
91+
/* eslint-disable camelcase */
92+
export {
93+
hijackHash as _TEST_ACCESS_hijackHash,
94+
forceRestClient as _TEST_ACCESS_forceRestClient
95+
} from './api/test_access';
96+
/* eslint-enable camelcase */

‎packages/database/src/api.ts

+2-79
Original file line numberDiff line numberDiff line change
@@ -15,82 +15,5 @@
1515
* limitations under the License.
1616
*/
1717

18-
export {
19-
Database,
20-
EmulatorMockTokenOptions,
21-
enableLogging,
22-
getDatabase,
23-
goOffline,
24-
goOnline,
25-
connectDatabaseEmulator
26-
} from './api/Database';
27-
export {
28-
Query,
29-
DatabaseReference,
30-
ListenOptions,
31-
Unsubscribe,
32-
ThenableReference
33-
} from './api/Reference';
34-
export { OnDisconnect } from './api/OnDisconnect';
35-
export {
36-
DataSnapshot,
37-
EventType,
38-
QueryConstraint,
39-
QueryConstraintType,
40-
endAt,
41-
endBefore,
42-
equalTo,
43-
get,
44-
limitToFirst,
45-
limitToLast,
46-
off,
47-
onChildAdded,
48-
onChildChanged,
49-
onChildMoved,
50-
onChildRemoved,
51-
onDisconnect,
52-
onValue,
53-
orderByChild,
54-
orderByKey,
55-
orderByPriority,
56-
orderByValue,
57-
push,
58-
query,
59-
ref,
60-
refFromURL,
61-
remove,
62-
set,
63-
setPriority,
64-
setWithPriority,
65-
startAfter,
66-
startAt,
67-
update,
68-
child
69-
} from './api/Reference_impl';
70-
export { increment, serverTimestamp } from './api/ServerValue';
71-
export {
72-
runTransaction,
73-
TransactionOptions,
74-
TransactionResult
75-
} from './api/Transaction';
76-
77-
// internal exports
78-
export { setSDKVersion as _setSDKVersion } from './core/version';
79-
export {
80-
ReferenceImpl as _ReferenceImpl,
81-
QueryImpl as _QueryImpl
82-
} from './api/Reference_impl';
83-
export { repoManagerDatabaseFromApp as _repoManagerDatabaseFromApp } from './api/Database';
84-
export {
85-
validatePathString as _validatePathString,
86-
validateWritablePath as _validateWritablePath
87-
} from './core/util/validation';
88-
export { UserCallback as _UserCallback } from './core/view/EventRegistration';
89-
export { QueryParams as _QueryParams } from './core/view/QueryParams';
90-
91-
/* eslint-disable camelcase */
92-
export {
93-
hijackHash as _TEST_ACCESS_hijackHash,
94-
forceRestClient as _TEST_ACCESS_forceRestClient
95-
} from './api/test_access';
96-
/* eslint-enable camelcase */
18+
export * from './api.standalone';
19+
export { getDatabase } from './api/Database';
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
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+
import { Client } from 'faye-websocket';
19+
20+
import { setWebSocketImpl } from './realtime/WebSocketConnection';
21+
22+
setWebSocketImpl(Client);
23+
24+
// This entry point should only be consumed by Admin SDK
25+
export * from './api.standalone';

0 commit comments

Comments
 (0)
Please sign in to comment.