Skip to content

FirebaseApp modularization #2709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions integration/shared/namespaceDefinition.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@
"removeApp": {
"__type": "function"
},
"components": {
"__type": "Map"
},
"ErrorFactory": {
"__type": "function"
},
Expand Down
41 changes: 41 additions & 0 deletions packages/app-types/next/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ComponentContainer } from '@firebase/component';

export interface FirebaseAppNext {
/**
* The (read-only) name (identifier) for this App. '[DEFAULT]' is the default
* App.
*/
readonly name: string;

/**
* The (read-only) configuration options from the app initialization.
*/
readonly options: FirebaseOptionsNext;

/**
* The settable config flag for GDPR opt-in/opt-out
*/
automaticDataCollectionEnabled: boolean;
}

export interface FirebaseAppInternalNext extends FirebaseAppNext {
container: ComponentContainer;
isDeleted: boolean;
checkDestroyed(): void;
}

export interface FirebaseOptionsNext {
apiKey?: string;
authDomain?: string;
databaseURL?: string;
projectId?: string;
storageBucket?: string;
messagingSenderId?: string;
appId?: string;
measurementId?: string;
}

export interface FirebaseAppConfigNext {
name?: string;
automaticDataCollectionEnabled?: boolean;
}
5 changes: 0 additions & 5 deletions packages/app-types/private.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,6 @@ export interface _FirebaseNamespace extends FirebaseNamespace {
*/
removeApp(name: string): void;

/**
* registered components.
*/
components: Map<string, Component>;

/*
* Convert service name to factory name to use.
*/
Expand Down
6 changes: 3 additions & 3 deletions packages/app/index.lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
* limitations under the License.
*/

import { createFirebaseNamespaceLite } from './src/lite/firebaseNamespaceLite';
import { registerCoreComponents } from './src/registerCoreComponents';
import { createFirebaseNamespaceLite } from './src/compat/lite/firebaseNamespaceLite';
import { registerCoreComponents } from './src/next/registerCoreComponents';

export const firebase = createFirebaseNamespaceLite();

registerCoreComponents(firebase, 'lite');
registerCoreComponents('lite');

// eslint-disable-next-line import/no-default-export
export default firebase;
6 changes: 3 additions & 3 deletions packages/app/index.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

import { FirebaseNamespace } from '@firebase/app-types';
import { _FirebaseNamespace } from '@firebase/app-types/private';
import { firebase as _firebase } from './src/firebaseNamespace';
import { firebase as _firebase } from './src/compat/firebaseNamespace';
// Node specific packages.
// @ts-ignore
import Storage from 'dom-storage';
// @ts-ignore
import { XMLHttpRequest } from 'xmlhttprequest';
import { registerCoreComponents } from './src/registerCoreComponents';
import { registerCoreComponents } from './src/next/registerCoreComponents';

(_firebase as _FirebaseNamespace).INTERNAL.extendNamespace({
INTERNAL: {
Expand All @@ -37,7 +37,7 @@ import { registerCoreComponents } from './src/registerCoreComponents';

export const firebase = _firebase as FirebaseNamespace;

registerCoreComponents(firebase, 'node');
registerCoreComponents('node');

// eslint-disable-next-line import/no-default-export
export default firebase;
6 changes: 3 additions & 3 deletions packages/app/index.rn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

import { FirebaseNamespace } from '@firebase/app-types';
import { _FirebaseNamespace } from '@firebase/app-types/private';
import { firebase as _firebase } from './src/firebaseNamespace';
import { registerCoreComponents } from './src/registerCoreComponents';
import { firebase as _firebase } from './src/compat/firebaseNamespace';
import { registerCoreComponents } from './src/next/registerCoreComponents';

/**
* To avoid having to include the @types/react-native package, which breaks
Expand All @@ -38,7 +38,7 @@ const { AsyncStorage } = require('react-native');

export const firebase = _firebase as FirebaseNamespace;

registerCoreComponents(firebase, 'rn');
registerCoreComponents('rn');

// eslint-disable-next-line import/no-default-export
export default firebase;
6 changes: 3 additions & 3 deletions packages/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
*/

import { FirebaseNamespace } from '@firebase/app-types';
import { firebase as firebaseNamespace } from './src/firebaseNamespace';
import { firebase as firebaseNamespace } from './src/compat/firebaseNamespace';
import { isNode, isBrowser } from '@firebase/util';
import { logger } from './src/logger';
import { registerCoreComponents } from './src/registerCoreComponents';
import { registerCoreComponents } from './src/next/registerCoreComponents';

// Firebase Lite detection
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -68,7 +68,7 @@ firebaseNamespace.initializeApp = function(...args: any) {

export const firebase = firebaseNamespace;

registerCoreComponents(firebase);
registerCoreComponents();

// eslint-disable-next-line import/no-default-export
export default firebase;
8 changes: 8 additions & 0 deletions packages/app/next/internal/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@firebase/app/next/internal",
"main": "../../dist/cjs/next/internal.js",
"browser": "../../dist/cjs/next/internal.js",
"module": "../../dist/esm5/next/internal.js",
"esm2017": "../../dist/esm2017/next/internal.js",
"typings": "../../dist/packages/app/src/next/internal.d.ts"
}
8 changes: 8 additions & 0 deletions packages/app/next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@firebase/app/next",
"main": "../dist/cjs/next.js",
"browser": "../dist/cjs/next.js",
"module": "../dist/esm5/next.js",
"esm2017": "../dist/esm2017/next.js",
"typings": "../dist/packages/app/src/next/index.d.ts"
}
8 changes: 4 additions & 4 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"description": "The primary entrypoint to the Firebase JS SDK",
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
"main": "dist/index.node.cjs.js",
"browser": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"browser": "dist/cjs/index.js",
"module": "dist/esm5/index.js",
"react-native": "dist/index.rn.cjs.js",
"esm2017": "dist/index.esm2017.js",
"esm2017": "dist/esm2017/index.js",
"lite": "dist/index.lite.js",
"lite-esm2017": "dist/index.lite.esm2017.js",
"files": [
Expand All @@ -22,7 +22,7 @@
"type-check": "tsc -p . --noEmit",
"test:browser": "karma start --single-run",
"test:browser:debug": "karma start --browsers Chrome --auto-watch",
"test:node": "TS_NODE_FILES=true TS_NODE_CACHE=NO TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha test/**/*.test.* --opts ../../config/mocha.node.opts",
"test:node": "TS_NODE_FILES=true TS_NODE_CACHE=NO TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha test/**/*.test.* src/**/*.test.ts --opts ../../config/mocha.node.opts",
"prepare": "yarn build"
},
"license": "Apache-2.0",
Expand Down
18 changes: 13 additions & 5 deletions packages/app/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@ const es5BuildPlugins = [

const es5Builds = [
{
input: 'index.ts',
input: {
index: 'index.ts',
next: 'src/next/index.ts',
'next/internal': 'src/next/internal.ts'
},
output: [
{ file: pkg.browser, format: 'cjs', sourcemap: true },
{ file: pkg.module, format: 'es', sourcemap: true }
{ dir: 'dist/cjs', format: 'cjs', sourcemap: true },
{ dir: 'dist/esm5', format: 'es', sourcemap: true }
],
plugins: es5BuildPlugins,
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
Expand Down Expand Up @@ -101,9 +105,13 @@ const es2017Builds = [
* Browser Builds
*/
{
input: 'index.ts',
input: {
index: 'index.ts',
next: 'src/next/index.ts',
'next/internal': 'src/next/internal.ts'
},
output: {
file: pkg.esm2017,
dir: 'dist/esm2017',
format: 'es',
sourcemap: true
},
Expand Down
135 changes: 135 additions & 0 deletions packages/app/src/compat/firebaseApp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* @license
* Copyright 2017 Google Inc.
*
* 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.
*/

import { FirebaseApp, FirebaseOptions } from '@firebase/app-types';
import {
_FirebaseApp,
_FirebaseNamespace,
FirebaseService
} from '@firebase/app-types/private';
import { Component, ComponentType, Name, ComponentContainer } from '@firebase/component';
import { DEFAULT_ENTRY_NAME } from '../constants';
import { FirebaseAppInternalNext } from '@firebase/app-types/next';
import { deleteApp } from '../next';
import { addComponent, addOrOverwriteComponent } from '../next/internal';

/**
* Global context object for a collection of services using
* a shared authentication state.
*/
export class FirebaseAppImpl implements FirebaseApp {
private readonly container: ComponentContainer;

constructor(
private readonly app: FirebaseAppInternalNext,
private readonly firebase: _FirebaseNamespace
) {
// add itself to container
addComponent(app, new Component('app', () => this, ComponentType.PUBLIC));
this.container = app.container;
}

get automaticDataCollectionEnabled(): boolean {
return this.app.automaticDataCollectionEnabled;
}

set automaticDataCollectionEnabled(val) {
this.app.automaticDataCollectionEnabled = val;
}

get name(): string {
return this.app.name;
}

get options(): FirebaseOptions {
return this.app.options;
}

delete(): Promise<void> {
return new Promise(resolve => {
this.app.checkDestroyed();
resolve();
}).then(() => {
this.firebase.INTERNAL.removeApp(this.name);
return deleteApp(this.app);
});
}

/**
* Return a service instance associated with this app (creating it
* on demand), identified by the passed instanceIdentifier.
*
* NOTE: Currently storage and functions are the only ones that are leveraging this
* functionality. They invoke it by calling:
*
* ```javascript
* firebase.app().storage('STORAGE BUCKET ID')
* ```
*
* The service name is passed to this already
* @internal
*/
_getService(
name: string,
instanceIdentifier: string = DEFAULT_ENTRY_NAME
): FirebaseService {
this.app.checkDestroyed();

// getImmediate will always succeed because _getService is only called for registered components.
return (this.app.container.getProvider(name as Name).getImmediate({
identifier: instanceIdentifier
}) as unknown) as FirebaseService;
}

/**
* Remove a service instance from the cache, so we will create a new instance for this service
* when people try to get it again.
*
* NOTE: currently only firestore uses this functionality to support firestore shutdown.
*
* @param name The service name
* @param instanceIdentifier instance identifier in case multiple instances are allowed
* @internal
*/
_removeServiceInstance(
name: string,
instanceIdentifier: string = DEFAULT_ENTRY_NAME
): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.app.container.getProvider(name as any)
.clearInstance(instanceIdentifier);
}

/**
* @param component the component being added to this app's container
* @internal
*/
_addComponent(component: Component): void {
addComponent(this.app, component);
}

_addOrOverwriteComponent(component: Component): void {
addOrOverwriteComponent(this.app, component);
}
}

// TODO: investigate why the following needs to be commented out
// Prevent dead-code elimination of these methods w/o invalid property
// copying.
// (FirebaseAppImpl.prototype.name && FirebaseAppImpl.prototype.options) ||
// FirebaseAppImpl.prototype.delete ||
// console.log('dc');
Loading