Skip to content

Commit b2bf4f3

Browse files
committed
app-compat impl
1 parent aa84b26 commit b2bf4f3

20 files changed

+1363
-51
lines changed

common/api-review/app-exp.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export function _clearComponents(): void;
2929
// @internal
3030
export const _components: Map<string, Component<any>>;
3131

32+
// @internal
33+
export const _DEFAULT_ENTRY_NAME = "[DEFAULT]";
34+
3235
// @public
3336
export function deleteApp(app: FirebaseApp): Promise<void>;
3437

packages-exp/app-compat/package.json

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
"version": "0.0.800",
44
"description": "The primary entrypoint to the Firebase JS SDK",
55
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
6-
"main": "dist/index.node.cjs.js",
7-
"browser": "dist/cjs/index.js",
8-
"module": "dist/esm5/index.js",
9-
"react-native": "dist/index.rn.cjs.js",
10-
"esm2017": "dist/esm2017/index.js",
6+
"main": "dist/index.cjs.js",
7+
"browser": "dist/index.esm5.js",
8+
"module": "dist/index.esm5.js",
9+
"esm2017": "dist/index.esm2017.js",
1110
"lite": "dist/index.lite.js",
1211
"lite-esm2017": "dist/index.lite.esm2017.js",
1312
"files": [
@@ -27,11 +26,11 @@
2726
},
2827
"license": "Apache-2.0",
2928
"dependencies": {
30-
"@firebase/app-types": "0.5.2",
31-
"@firebase/util": "0.2.41",
32-
"@firebase/logger": "0.1.36",
33-
"@firebase/component": "0.1.6",
34-
"tslib": "1.11.1",
29+
"@firebase/app-exp": "0.0.800",
30+
"@firebase/util": "0.3.0",
31+
"@firebase/logger": "0.2.6",
32+
"@firebase/component": "0.1.17",
33+
"tslib": "^1.11.1",
3534
"dom-storage": "2.1.0",
3635
"xmlhttprequest": "1.8.0"
3736
},
@@ -50,11 +49,11 @@
5049
"bugs": {
5150
"url": "https://github.com/firebase/firebase-js-sdk/issues"
5251
},
53-
"typings": "dist/packages/app/index.d.ts",
52+
"typings": "dist/src/index.d.ts",
5453
"nyc": {
5554
"extension": [
5655
".ts"
5756
],
5857
"reportDir": "./coverage/node"
5958
}
60-
}
59+
}

packages-exp/app-compat/rollup.config.js

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,43 +36,16 @@ const es5BuildPlugins = [
3636

3737
const es5Builds = [
3838
{
39-
input: {
40-
index: 'index.ts',
41-
next: 'src/next/index.ts',
42-
'next/internal': 'src/next/internal.ts'
43-
},
39+
input: 'src/index.ts',
4440
output: [
45-
{ dir: 'dist/cjs', format: 'cjs', sourcemap: true },
46-
{ dir: 'dist/esm5', format: 'es', sourcemap: true }
41+
{ file: pkg.main, format: 'cjs', sourcemap: true },
42+
{ file: pkg.module, format: 'es', sourcemap: true }
4743
],
4844
plugins: es5BuildPlugins,
4945
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
5046
},
5147
{
52-
input: 'index.node.ts',
53-
output: {
54-
file: pkg.main,
55-
format: 'cjs',
56-
sourcemap: true
57-
},
58-
plugins: es5BuildPlugins,
59-
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
60-
},
61-
{
62-
input: 'index.rn.ts',
63-
output: {
64-
file: pkg['react-native'],
65-
format: 'cjs',
66-
sourcemap: true
67-
},
68-
plugins: es5BuildPlugins,
69-
external: id =>
70-
[...deps, 'react-native'].some(
71-
dep => id === dep || id.startsWith(`${dep}/`)
72-
)
73-
},
74-
{
75-
input: 'index.lite.ts',
48+
input: 'src/index.lite.ts',
7649
output: {
7750
file: pkg.lite,
7851
format: 'es',
@@ -105,21 +78,17 @@ const es2017Builds = [
10578
* Browser Builds
10679
*/
10780
{
108-
input: {
109-
index: 'index.ts',
110-
next: 'src/next/index.ts',
111-
'next/internal': 'src/next/internal.ts'
112-
},
81+
input: 'src/index.ts',
11382
output: {
114-
dir: 'dist/esm2017',
83+
file: pkg.esm2017,
11584
format: 'es',
11685
sourcemap: true
11786
},
11887
plugins: es2017BuildPlugins,
11988
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
12089
},
12190
{
122-
input: 'index.lite.ts',
91+
input: 'src/index.lite.ts',
12392
output: {
12493
file: pkg['lite-esm2017'],
12594
format: 'es',

packages-exp/app-compat/src/errors.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @license
3+
* Copyright 2019 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 { ErrorFactory, ErrorMap } from '@firebase/util';
19+
20+
export const enum AppError {
21+
NO_APP = 'no-app',
22+
INVALID_APP_ARGUMENT = 'invalid-app-argument'
23+
}
24+
25+
const ERRORS: ErrorMap<AppError> = {
26+
[AppError.NO_APP]:
27+
"No Firebase App '{$appName}' has been created - " +
28+
'call Firebase App.initializeApp()',
29+
[AppError.INVALID_APP_ARGUMENT]:
30+
'firebase.{$appName}() takes either no argument or a ' +
31+
'Firebase App instance.'
32+
};
33+
34+
type ErrorParams = { [key in AppError]: { appName: string } };
35+
36+
export const ERROR_FACTORY = new ErrorFactory<AppError, ErrorParams>(
37+
'app-compat',
38+
'Firebase',
39+
ERRORS
40+
);
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* @license
3+
* Copyright 2017 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, FirebaseOptions } from '@firebase/app-types';
19+
import {
20+
_FirebaseApp,
21+
_FirebaseNamespace,
22+
FirebaseService
23+
} from '@firebase/app-types/private';
24+
import {
25+
Component,
26+
ComponentType,
27+
Name,
28+
ComponentContainer
29+
} from '@firebase/component';
30+
import { _FirebaseAppInternal } from '@firebase/app-types-exp';
31+
import {
32+
deleteApp,
33+
_addComponent,
34+
_addOrOverwriteComponent,
35+
_DEFAULT_ENTRY_NAME
36+
} from '@firebase/app-exp';
37+
38+
/**
39+
* Global context object for a collection of services using
40+
* a shared authentication state.
41+
*/
42+
export class FirebaseAppImpl implements FirebaseApp {
43+
private readonly container: ComponentContainer;
44+
45+
constructor(
46+
private readonly app: _FirebaseAppInternal,
47+
private readonly firebase: _FirebaseNamespace
48+
) {
49+
// add itself to container
50+
// TODO: change the component name to 'app-compat' before the official release
51+
_addComponent(app, new Component('app', () => this, ComponentType.PUBLIC));
52+
this.container = app.container;
53+
}
54+
55+
get automaticDataCollectionEnabled(): boolean {
56+
return this.app.automaticDataCollectionEnabled;
57+
}
58+
59+
set automaticDataCollectionEnabled(val) {
60+
this.app.automaticDataCollectionEnabled = val;
61+
}
62+
63+
get name(): string {
64+
return this.app.name;
65+
}
66+
67+
get options(): FirebaseOptions {
68+
return this.app.options;
69+
}
70+
71+
delete(): Promise<void> {
72+
return new Promise(resolve => {
73+
this.app.checkDestroyed();
74+
resolve();
75+
}).then(() => {
76+
this.firebase.INTERNAL.removeApp(this.name);
77+
return deleteApp(this.app);
78+
});
79+
}
80+
81+
/**
82+
* Return a service instance associated with this app (creating it
83+
* on demand), identified by the passed instanceIdentifier.
84+
*
85+
* NOTE: Currently storage and functions are the only ones that are leveraging this
86+
* functionality. They invoke it by calling:
87+
*
88+
* ```javascript
89+
* firebase.app().storage('STORAGE BUCKET ID')
90+
* ```
91+
*
92+
* The service name is passed to this already
93+
* @internal
94+
*/
95+
_getService(
96+
name: string,
97+
instanceIdentifier: string = _DEFAULT_ENTRY_NAME
98+
): FirebaseService {
99+
this.app.checkDestroyed();
100+
101+
// getImmediate will always succeed because _getService is only called for registered components.
102+
return (this.app.container.getProvider(name as Name).getImmediate({
103+
identifier: instanceIdentifier
104+
}) as unknown) as FirebaseService;
105+
}
106+
107+
/**
108+
* Remove a service instance from the cache, so we will create a new instance for this service
109+
* when people try to get it again.
110+
*
111+
* NOTE: currently only firestore uses this functionality to support firestore shutdown.
112+
*
113+
* @param name The service name
114+
* @param instanceIdentifier instance identifier in case multiple instances are allowed
115+
* @internal
116+
*/
117+
_removeServiceInstance(
118+
name: string,
119+
instanceIdentifier: string = _DEFAULT_ENTRY_NAME
120+
): void {
121+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
122+
this.app.container
123+
.getProvider(name as any)
124+
.clearInstance(instanceIdentifier);
125+
}
126+
127+
/**
128+
* @param component the component being added to this app's container
129+
* @internal
130+
*/
131+
_addComponent(component: Component): void {
132+
_addComponent(this.app, component);
133+
}
134+
135+
_addOrOverwriteComponent(component: Component): void {
136+
_addOrOverwriteComponent(this.app, component);
137+
}
138+
}
139+
140+
// TODO: investigate why the following needs to be commented out
141+
// Prevent dead-code elimination of these methods w/o invalid property
142+
// copying.
143+
// (FirebaseAppImpl.prototype.name && FirebaseAppImpl.prototype.options) ||
144+
// FirebaseAppImpl.prototype.delete ||
145+
// console.log('dc');
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* @license
3+
* Copyright 2019 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 { FirebaseNamespace } from '@firebase/app-types';
19+
import { _FirebaseApp, _FirebaseNamespace } from '@firebase/app-types/private';
20+
import { createSubscribe, deepExtend, ErrorFactory } from '@firebase/util';
21+
import { FirebaseAppImpl } from './firebaseApp';
22+
import { createFirebaseNamespaceCore } from './firebaseNamespaceCore';
23+
24+
/**
25+
* Return a firebase namespace object.
26+
*
27+
* In production, this will be called exactly once and the result
28+
* assigned to the 'firebase' global. It may be called multiple times
29+
* in unit tests.
30+
*/
31+
export function createFirebaseNamespace(): FirebaseNamespace {
32+
const namespace = createFirebaseNamespaceCore(FirebaseAppImpl);
33+
(namespace as _FirebaseNamespace).INTERNAL = {
34+
...(namespace as _FirebaseNamespace).INTERNAL,
35+
createFirebaseNamespace,
36+
extendNamespace,
37+
createSubscribe,
38+
ErrorFactory,
39+
deepExtend
40+
};
41+
42+
/**
43+
* Patch the top-level firebase namespace with additional properties.
44+
*
45+
* firebase.INTERNAL.extendNamespace()
46+
*/
47+
function extendNamespace(props: { [prop: string]: unknown }): void {
48+
deepExtend(namespace, props);
49+
}
50+
51+
return namespace;
52+
}
53+
54+
export const firebase = createFirebaseNamespace();

0 commit comments

Comments
 (0)