Skip to content

Commit dfe65ff

Browse files
authored
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

File tree

12 files changed

+276
-165
lines changed

12 files changed

+276
-165
lines changed

.changeset/afraid-boxes-roll.md

Lines changed: 6 additions & 0 deletions
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

Lines changed: 13 additions & 0 deletions
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

Lines changed: 31 additions & 3 deletions
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

Lines changed: 5 additions & 68 deletions
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';
Lines changed: 68 additions & 0 deletions
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

Lines changed: 8 additions & 14 deletions
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?: {
Lines changed: 7 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 14 additions & 1 deletion
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
/**

0 commit comments

Comments
 (0)