diff --git a/.changeset/thin-bikes-tan.md b/.changeset/thin-bikes-tan.md new file mode 100644 index 00000000000..121b3208d52 --- /dev/null +++ b/.changeset/thin-bikes-tan.md @@ -0,0 +1,6 @@ +--- +'@firebase/app': minor +'firebase': minor +--- + +initializeServerApp now supports auto-initialization for Firebase App Hosting. diff --git a/common/api-review/app.api.md b/common/api-review/app.api.md index 4e93f1ae87f..c12089c1520 100644 --- a/common/api-review/app.api.md +++ b/common/api-review/app.api.md @@ -110,14 +110,20 @@ export function initializeApp(options: FirebaseOptions, config?: FirebaseAppSett export function initializeApp(): FirebaseApp; // @public -export function initializeServerApp(options: FirebaseOptions | FirebaseApp, config: FirebaseServerAppSettings): FirebaseServerApp; +export function initializeServerApp(options: FirebaseOptions | FirebaseApp, config?: FirebaseServerAppSettings): FirebaseServerApp; + +// @public +export function initializeServerApp(config?: FirebaseServerAppSettings): FirebaseServerApp; // @internal (undocumented) -export function _isFirebaseApp(obj: FirebaseApp | FirebaseOptions): obj is FirebaseApp; +export function _isFirebaseApp(obj: FirebaseApp | FirebaseOptions | FirebaseAppSettings): obj is FirebaseApp; // @internal (undocumented) export function _isFirebaseServerApp(obj: FirebaseApp | FirebaseServerApp | null | undefined): obj is FirebaseServerApp; +// @internal (undocumented) +export function _isFirebaseServerAppSettings(obj: FirebaseApp | FirebaseOptions | FirebaseAppSettings): obj is FirebaseServerAppSettings; + // @public export function onLog(logCallback: LogCallback | null, options?: LogOptions): void; diff --git a/docs-devsite/app.md b/docs-devsite/app.md index 9c3b322aaaf..0c9b2d03e4b 100644 --- a/docs-devsite/app.md +++ b/docs-devsite/app.md @@ -23,6 +23,8 @@ This package coordinates the communication between the different Firebase compon | function() | | [getApps()](./app.md#getapps) | A (read-only) array of all initialized apps. | | [initializeApp()](./app.md#initializeapp) | Creates and initializes a FirebaseApp instance. | +| function(config, ...) | +| [initializeServerApp(config)](./app.md#initializeserverapp_e7d0728) | Creates and initializes a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) instance. | | function(libraryKeyOrName, ...) | | [registerVersion(libraryKeyOrName, version, variant)](./app.md#registerversion_f673248) | Registers a library's name and version for platform logging purposes. | | function(logCallback, ...) | @@ -116,6 +118,38 @@ export declare function initializeApp(): FirebaseApp; [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) +## function(config, ...) + +### initializeServerApp(config) {:#initializeserverapp_e7d0728} + +Creates and initializes a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) instance. + +Signature: + +```typescript +export declare function initializeServerApp(config?: FirebaseServerAppSettings): FirebaseServerApp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | [FirebaseServerAppSettings](./app.firebaseserverappsettings.md#firebaseserverappsettings_interface) | Optional FirebaseServerApp settings. | + +Returns: + +[FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) + +The initialized `FirebaseServerApp`. + +#### Exceptions + +If invoked in an unsupported non-server environment such as a browser. + +If [FirebaseServerAppSettings.releaseOnDeref](./app.firebaseserverappsettings.md#firebaseserverappsettingsreleaseonderef) is defined but the runtime doesn't provide Finalization Registry support. + +If the `FIREBASE_OPTIONS` enviornment variable does not contain a valid project configuration required for auto-initialization. + ## function(libraryKeyOrName, ...) ### registerVersion(libraryKeyOrName, version, variant) {:#registerversion_f673248} @@ -260,6 +294,12 @@ export declare function initializeApp(options: FirebaseOptions, name?: string): The initialized app. +#### Exceptions + +If the optional `name` parameter is malformed or empty. + +If a `FirebaseApp` already exists with the same name but with a different configuration. + ### Example 1 @@ -312,6 +352,12 @@ export declare function initializeApp(options: FirebaseOptions, config?: Firebas [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) +#### Exceptions + +If [FirebaseAppSettings.name](./app.firebaseappsettings.md#firebaseappsettingsname) is defined but the value is malformed or empty. + +If a `FirebaseApp` already exists with the same name but with a different configuration. + ### initializeServerApp(options, config) {:#initializeserverapp_30ab697} Creates and initializes a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) instance. @@ -323,7 +369,7 @@ See [Add Firebase to your app](https://firebase.google.com/docs/web/setup#add_fi Signature: ```typescript -export declare function initializeServerApp(options: FirebaseOptions | FirebaseApp, config: FirebaseServerAppSettings): FirebaseServerApp; +export declare function initializeServerApp(options: FirebaseOptions | FirebaseApp, config?: FirebaseServerAppSettings): FirebaseServerApp; ``` #### Parameters @@ -331,7 +377,7 @@ export declare function initializeServerApp(options: FirebaseOptions | FirebaseA | Parameter | Type | Description | | --- | --- | --- | | options | [FirebaseOptions](./app.firebaseoptions.md#firebaseoptions_interface) \| [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | Firebase.AppOptions to configure the app's services, or a a FirebaseApp instance which contains the AppOptions within. | -| config | [FirebaseServerAppSettings](./app.firebaseserverappsettings.md#firebaseserverappsettings_interface) | FirebaseServerApp configuration. | +| config | [FirebaseServerAppSettings](./app.firebaseserverappsettings.md#firebaseserverappsettings_interface) | Optional FirebaseServerApp settings. | Returns: @@ -339,6 +385,12 @@ export declare function initializeServerApp(options: FirebaseOptions | FirebaseA The initialized `FirebaseServerApp`. +#### Exceptions + +If invoked in an unsupported non-server environment such as a browser. + +If [FirebaseServerAppSettings.releaseOnDeref](./app.firebaseserverappsettings.md#firebaseserverappsettingsreleaseonderef) is defined but the runtime doesn't provide Finalization Registry support. + ### Example diff --git a/packages/app/src/api.ts b/packages/app/src/api.ts index 9cba8ec6f50..6fd50060a6a 100644 --- a/packages/app/src/api.ts +++ b/packages/app/src/api.ts @@ -37,6 +37,7 @@ import { _apps, _components, _isFirebaseApp, + _isFirebaseServerAppSettings, _registerComponent, _serverApps } from './internal'; @@ -106,6 +107,10 @@ export const SDK_VERSION = version; * * @returns The initialized app. * + * @throws If the optional `name` parameter is malformed or empty. + * + * @throws If a `FirebaseApp` already exists with the same name but with a different configuration. + * * @public */ export function initializeApp( @@ -118,6 +123,9 @@ export function initializeApp( * @param options - Options to configure the app's services. * @param config - FirebaseApp Configuration * + * @throws If {@link FirebaseAppSettings.name} is defined but the value is malformed or empty. + * + * @throws If a `FirebaseApp` already exists with the same name but with a different configuration. * @public */ export function initializeApp( @@ -220,41 +228,75 @@ export function initializeApp( * * @param options - `Firebase.AppOptions` to configure the app's services, or a * a `FirebaseApp` instance which contains the `AppOptions` within. - * @param config - `FirebaseServerApp` configuration. + * @param config - Optional `FirebaseServerApp` settings. * * @returns The initialized `FirebaseServerApp`. * + * @throws If invoked in an unsupported non-server environment such as a browser. + * + * @throws If {@link FirebaseServerAppSettings.releaseOnDeref} is defined but the runtime doesn't + * provide Finalization Registry support. + * * @public */ export function initializeServerApp( options: FirebaseOptions | FirebaseApp, - config: FirebaseServerAppSettings + config?: FirebaseServerAppSettings ): FirebaseServerApp; +/** + * Creates and initializes a {@link @firebase/app#FirebaseServerApp} instance. + * + * @param config - Optional `FirebaseServerApp` settings. + * + * @returns The initialized `FirebaseServerApp`. + * + * @throws If invoked in an unsupported non-server environment such as a browser. + * @throws If {@link FirebaseServerAppSettings.releaseOnDeref} is defined but the runtime doesn't + * provide Finalization Registry support. + * @throws If the `FIREBASE_OPTIONS` enviornment variable does not contain a valid project + * configuration required for auto-initialization. + * + * @public + */ export function initializeServerApp( - _options: FirebaseOptions | FirebaseApp, - _serverAppConfig: FirebaseServerAppSettings + config?: FirebaseServerAppSettings +): FirebaseServerApp; +export function initializeServerApp( + _options?: FirebaseApp | FirebaseServerAppSettings | FirebaseOptions, + _serverAppConfig: FirebaseServerAppSettings = {} ): FirebaseServerApp { if (isBrowser() && !isWebWorker()) { // FirebaseServerApp isn't designed to be run in browsers. throw ERROR_FACTORY.create(AppError.INVALID_SERVER_APP_ENVIRONMENT); } - if (_serverAppConfig.automaticDataCollectionEnabled === undefined) { - _serverAppConfig.automaticDataCollectionEnabled = true; + let firebaseOptions: FirebaseOptions | undefined; + let serverAppSettings: FirebaseServerAppSettings = _serverAppConfig || {}; + + if (_options) { + if (_isFirebaseApp(_options)) { + firebaseOptions = _options.options; + } else if (_isFirebaseServerAppSettings(_options)) { + serverAppSettings = _options; + } else { + firebaseOptions = _options; + } } - let appOptions: FirebaseOptions; - if (_isFirebaseApp(_options)) { - appOptions = _options.options; - } else { - appOptions = _options; + if (serverAppSettings.automaticDataCollectionEnabled === undefined) { + serverAppSettings.automaticDataCollectionEnabled = true; + } + + firebaseOptions ||= getDefaultAppConfig(); + if (!firebaseOptions) { + throw ERROR_FACTORY.create(AppError.NO_OPTIONS); } // Build an app name based on a hash of the configuration options. const nameObj = { - ..._serverAppConfig, - ...appOptions + ...serverAppSettings, + ...firebaseOptions }; // However, Do not mangle the name based on releaseOnDeref, since it will vary between the @@ -270,7 +312,7 @@ export function initializeServerApp( ); }; - if (_serverAppConfig.releaseOnDeref !== undefined) { + if (serverAppSettings.releaseOnDeref !== undefined) { if (typeof FinalizationRegistry === 'undefined') { throw ERROR_FACTORY.create( AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED, @@ -283,7 +325,7 @@ export function initializeServerApp( const existingApp = _serverApps.get(nameString) as FirebaseServerApp; if (existingApp) { (existingApp as FirebaseServerAppImpl).incRefCount( - _serverAppConfig.releaseOnDeref + serverAppSettings.releaseOnDeref ); return existingApp; } @@ -294,8 +336,8 @@ export function initializeServerApp( } const newApp = new FirebaseServerAppImpl( - appOptions, - _serverAppConfig, + firebaseOptions, + serverAppSettings, nameString, container ); diff --git a/packages/app/src/internal.ts b/packages/app/src/internal.ts index cbcdcb26501..422c941aba3 100644 --- a/packages/app/src/internal.ts +++ b/packages/app/src/internal.ts @@ -17,6 +17,8 @@ import { FirebaseApp, + FirebaseAppSettings, + FirebaseServerAppSettings, FirebaseOptions, FirebaseServerApp } from './public-types'; @@ -147,18 +149,40 @@ export function _removeServiceInstance( /** * - * @param obj - an object of type FirebaseApp or FirebaseOptions. + * @param obj - an object of type FirebaseApp, FirebaseOptions or FirebaseAppSettings. * * @returns true if the provide object is of type FirebaseApp. * * @internal */ export function _isFirebaseApp( - obj: FirebaseApp | FirebaseOptions + obj: FirebaseApp | FirebaseOptions | FirebaseAppSettings ): obj is FirebaseApp { return (obj as FirebaseApp).options !== undefined; } +/** + * + * @param obj - an object of type FirebaseApp, FirebaseOptions or FirebaseAppSettings. + * + * @returns true if the provided object is of type FirebaseServerAppImpl. + * + * @internal + */ +export function _isFirebaseServerAppSettings( + obj: FirebaseApp | FirebaseOptions | FirebaseAppSettings +): obj is FirebaseServerAppSettings { + if (_isFirebaseApp(obj)) { + return false; + } + return ( + 'authIdToken' in obj || + 'appCheckToken' in obj || + 'releaseOnDeref' in obj || + 'automaticDataCollectionEnabled' in obj + ); +} + /** * * @param obj - an object of type FirebaseApp.