diff --git a/etc/firebase-admin.api.md b/etc/firebase-admin.api.md index f67bf14aee..de8a48d4a9 100644 --- a/etc/firebase-admin.api.md +++ b/etc/firebase-admin.api.md @@ -819,86 +819,62 @@ export namespace projectManagement { export function refreshToken(refreshTokenPathOrObject: string | object, httpAgent?: Agent): Credential; // @public -export function remoteConfig(app?: app.App): remoteConfig.RemoteConfig; +export function remoteConfig(app?: App): remoteConfig.RemoteConfig; // @public (undocumented) export namespace remoteConfig { - export interface ExplicitParameterValue { - value: string; - } - export interface InAppDefaultValue { - useInAppDefault: boolean; - } - export interface ListVersionsOptions { - endTime?: Date | string; - endVersionNumber?: string | number; - pageSize?: number; - pageToken?: string; - startTime?: Date | string; - } - export interface ListVersionsResult { - nextPageToken?: string; - versions: Version[]; - } - export interface RemoteConfig { - // (undocumented) - app: app.App; - createTemplateFromJSON(json: string): RemoteConfigTemplate; - getTemplate(): Promise; - getTemplateAtVersion(versionNumber: number | string): Promise; - listVersions(options?: ListVersionsOptions): Promise; - publishTemplate(template: RemoteConfigTemplate, options?: { - force: boolean; - }): Promise; - rollback(versionNumber: string | number): Promise; - validateTemplate(template: RemoteConfigTemplate): Promise; - } - export interface RemoteConfigCondition { - expression: string; - name: string; - tagColor?: TagColor; - } - export interface RemoteConfigParameter { - conditionalValues?: { - [key: string]: RemoteConfigParameterValue; - }; - defaultValue?: RemoteConfigParameterValue; - description?: string; - } - export interface RemoteConfigParameterGroup { - description?: string; - parameters: { - [key: string]: RemoteConfigParameter; - }; - } - export type RemoteConfigParameterValue = ExplicitParameterValue | InAppDefaultValue; - export interface RemoteConfigTemplate { - conditions: RemoteConfigCondition[]; - readonly etag: string; - parameterGroups: { - [key: string]: RemoteConfigParameterGroup; - }; - parameters: { - [key: string]: RemoteConfigParameter; - }; - version?: Version; - } - export interface RemoteConfigUser { - email: string; - imageUrl?: string; - name?: string; - } - export type TagColor = 'BLUE' | 'BROWN' | 'CYAN' | 'DEEP_ORANGE' | 'GREEN' | 'INDIGO' | 'LIME' | 'ORANGE' | 'PINK' | 'PURPLE' | 'TEAL'; - export interface Version { - description?: string; - isLegacy?: boolean; - rollbackSource?: string; - updateOrigin?: ('REMOTE_CONFIG_UPDATE_ORIGIN_UNSPECIFIED' | 'CONSOLE' | 'REST_API' | 'ADMIN_SDK_NODE'); - updateTime?: string; - updateType?: ('REMOTE_CONFIG_UPDATE_TYPE_UNSPECIFIED' | 'INCREMENTAL_UPDATE' | 'FORCED_UPDATE' | 'ROLLBACK'); - updateUser?: RemoteConfigUser; - versionNumber?: string; - } + // Warning: (ae-forgotten-export) The symbol "ExplicitParameterValue" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type ExplicitParameterValue = ExplicitParameterValue; + // Warning: (ae-forgotten-export) The symbol "InAppDefaultValue" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type InAppDefaultValue = InAppDefaultValue; + // Warning: (ae-forgotten-export) The symbol "ListVersionsOptions" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type ListVersionsOptions = ListVersionsOptions; + // Warning: (ae-forgotten-export) The symbol "ListVersionsResult" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type ListVersionsResult = ListVersionsResult; + // Warning: (ae-forgotten-export) The symbol "RemoteConfig" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfig = RemoteConfig; + // Warning: (ae-forgotten-export) The symbol "RemoteConfigCondition" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfigCondition = RemoteConfigCondition; + // Warning: (ae-forgotten-export) The symbol "RemoteConfigParameter" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfigParameter = RemoteConfigParameter; + // Warning: (ae-forgotten-export) The symbol "RemoteConfigParameterGroup" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfigParameterGroup = RemoteConfigParameterGroup; + // Warning: (ae-forgotten-export) The symbol "RemoteConfigParameterValue" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfigParameterValue = RemoteConfigParameterValue; + // Warning: (ae-forgotten-export) The symbol "RemoteConfigTemplate" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfigTemplate = RemoteConfigTemplate; + // Warning: (ae-forgotten-export) The symbol "RemoteConfigUser" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type RemoteConfigUser = RemoteConfigUser; + // Warning: (ae-forgotten-export) The symbol "TagColor" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type TagColor = TagColor; + // Warning: (ae-forgotten-export) The symbol "Version" needs to be exported by the entry point default-namespace.d.ts + // + // (undocumented) + export type Version = Version; } // @public (undocumented) diff --git a/etc/firebase-admin.remote-config.api.md b/etc/firebase-admin.remote-config.api.md new file mode 100644 index 0000000000..eee1507fba --- /dev/null +++ b/etc/firebase-admin.remote-config.api.md @@ -0,0 +1,152 @@ +## API Report File for "firebase-admin.remote-config" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { Agent } from 'http'; + +// @public +export interface ExplicitParameterValue { + value: string; +} + +// Warning: (ae-forgotten-export) The symbol "App" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export function getRemoteConfig(app?: App): RemoteConfig; + +// @public +export interface InAppDefaultValue { + useInAppDefault: boolean; +} + +// @public +export interface ListVersionsOptions { + endTime?: Date | string; + endVersionNumber?: string | number; + pageSize?: number; + pageToken?: string; + startTime?: Date | string; +} + +// @public +export interface ListVersionsResult { + nextPageToken?: string; + versions: Version[]; +} + +// @public +export class RemoteConfig { + // (undocumented) + readonly app: App; + createTemplateFromJSON(json: string): RemoteConfigTemplate; + getTemplate(): Promise; + getTemplateAtVersion(versionNumber: number | string): Promise; + listVersions(options?: ListVersionsOptions): Promise; + publishTemplate(template: RemoteConfigTemplate, options?: { + force: boolean; + }): Promise; + rollback(versionNumber: number | string): Promise; + validateTemplate(template: RemoteConfigTemplate): Promise; +} + +// @public +export function remoteConfig(app?: App): remoteConfig.RemoteConfig; + +// @public (undocumented) +export namespace remoteConfig { + // (undocumented) + export type ExplicitParameterValue = ExplicitParameterValue; + // (undocumented) + export type InAppDefaultValue = InAppDefaultValue; + // (undocumented) + export type ListVersionsOptions = ListVersionsOptions; + // (undocumented) + export type ListVersionsResult = ListVersionsResult; + // (undocumented) + export type RemoteConfig = RemoteConfig; + // (undocumented) + export type RemoteConfigCondition = RemoteConfigCondition; + // (undocumented) + export type RemoteConfigParameter = RemoteConfigParameter; + // (undocumented) + export type RemoteConfigParameterGroup = RemoteConfigParameterGroup; + // (undocumented) + export type RemoteConfigParameterValue = RemoteConfigParameterValue; + // (undocumented) + export type RemoteConfigTemplate = RemoteConfigTemplate; + // (undocumented) + export type RemoteConfigUser = RemoteConfigUser; + // (undocumented) + export type TagColor = TagColor; + // (undocumented) + export type Version = Version; +} + +// @public +export interface RemoteConfigCondition { + expression: string; + name: string; + tagColor?: TagColor; +} + +// @public +export interface RemoteConfigParameter { + conditionalValues?: { + [key: string]: RemoteConfigParameterValue; + }; + defaultValue?: RemoteConfigParameterValue; + description?: string; +} + +// @public +export interface RemoteConfigParameterGroup { + description?: string; + parameters: { + [key: string]: RemoteConfigParameter; + }; +} + +// @public +export type RemoteConfigParameterValue = ExplicitParameterValue | InAppDefaultValue; + +// @public +export interface RemoteConfigTemplate { + conditions: RemoteConfigCondition[]; + readonly etag: string; + parameterGroups: { + [key: string]: RemoteConfigParameterGroup; + }; + parameters: { + [key: string]: RemoteConfigParameter; + }; + version?: Version; +} + +// @public +export interface RemoteConfigUser { + email: string; + imageUrl?: string; + name?: string; +} + +// @public +export type TagColor = 'BLUE' | 'BROWN' | 'CYAN' | 'DEEP_ORANGE' | 'GREEN' | 'INDIGO' | 'LIME' | 'ORANGE' | 'PINK' | 'PURPLE' | 'TEAL'; + +// @public +export interface Version { + description?: string; + isLegacy?: boolean; + rollbackSource?: string; + updateOrigin?: ('REMOTE_CONFIG_UPDATE_ORIGIN_UNSPECIFIED' | 'CONSOLE' | 'REST_API' | 'ADMIN_SDK_NODE'); + updateTime?: string; + updateType?: ('REMOTE_CONFIG_UPDATE_TYPE_UNSPECIFIED' | 'INCREMENTAL_UPDATE' | 'FORCED_UPDATE' | 'ROLLBACK'); + updateUser?: RemoteConfigUser; + versionNumber?: string; +} + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/generate-reports.js b/generate-reports.js index 7a0c95bdc1..b9444e9088 100644 --- a/generate-reports.js +++ b/generate-reports.js @@ -39,6 +39,7 @@ const entryPoints = { 'firebase-admin/database': './lib/database/index.d.ts', 'firebase-admin/firestore': './lib/firestore/index.d.ts', 'firebase-admin/instance-id': './lib/instance-id/index.d.ts', + 'firebase-admin/remote-config': './lib/remote-config/index.d.ts', }; const tempConfigFile = 'api-extractor.tmp'; diff --git a/gulpfile.js b/gulpfile.js index b759ed89f9..d15c4acc57 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -92,6 +92,7 @@ gulp.task('compile', function() { 'lib/database/*.d.ts', 'lib/firestore/*.d.ts', 'lib/instance-id/*.d.ts', + 'lib/remote-config/*.d.ts', '!lib/utils/index.d.ts', ]; diff --git a/src/app/firebase-app.ts b/src/app/firebase-app.ts index 40a3415b4a..ff5bfd836f 100644 --- a/src/app/firebase-app.ts +++ b/src/app/firebase-app.ts @@ -32,7 +32,7 @@ import { Firestore } from '@google-cloud/firestore'; import { InstanceId } from '../instance-id/index'; import { ProjectManagement } from '../project-management/project-management'; import { SecurityRules } from '../security-rules/security-rules'; -import { RemoteConfig } from '../remote-config/remote-config'; +import { RemoteConfig } from '../remote-config/index'; /** * Type representing a callback which is called every time an app lifecycle event occurs. @@ -371,10 +371,8 @@ export class FirebaseApp implements app.App { * @return The RemoteConfig service instance of this app. */ public remoteConfig(): RemoteConfig { - return this.ensureService_('remoteConfig', () => { - const remoteConfigService: typeof RemoteConfig = require('../remote-config/remote-config').RemoteConfig; - return new remoteConfigService(this); - }); + const fn = require('../remote-config/index').getRemoteConfig; + return fn(this); } /** diff --git a/src/remote-config/index.ts b/src/remote-config/index.ts index 668fee3372..b7fd3fc15e 100644 --- a/src/remote-config/index.ts +++ b/src/remote-config/index.ts @@ -14,7 +14,50 @@ * limitations under the License. */ -import { app } from '../firebase-namespace-api'; +import { App, getApp } from '../app'; +import { FirebaseApp } from '../app/firebase-app'; +import { RemoteConfig } from './remote-config'; + +export { + ExplicitParameterValue, + InAppDefaultValue, + ListVersionsOptions, + ListVersionsResult, + RemoteConfigCondition, + RemoteConfigParameter, + RemoteConfigParameterGroup, + RemoteConfigParameterValue, + RemoteConfigTemplate, + RemoteConfigUser, + TagColor, + Version, +} from './remote-config-api'; +export { RemoteConfig } from './remote-config'; + +export function getRemoteConfig(app?: App): RemoteConfig { + if (typeof app === 'undefined') { + app = getApp(); + } + + const firebaseApp: FirebaseApp = app as FirebaseApp; + return firebaseApp.getOrInitService('remoteConfig', (app) => new RemoteConfig(app)); +} + +import { + ExplicitParameterValue as TExplicitParameterValue, + InAppDefaultValue as TInAppDefaultValue, + ListVersionsOptions as TListVersionsOptions, + ListVersionsResult as TListVersionsResult, + RemoteConfigCondition as TRemoteConfigCondition, + RemoteConfigParameter as TRemoteConfigParameter, + RemoteConfigParameterGroup as TRemoteConfigParameterGroup, + RemoteConfigParameterValue as TRemoteConfigParameterValue, + RemoteConfigTemplate as TRemoteConfigTemplate, + RemoteConfigUser as TRemoteConfigUser, + TagColor as TTagColor, + Version as TVersion, +} from './remote-config-api'; +import { RemoteConfig as TRemoteConfig } from './remote-config'; /** * Gets the {@link remoteConfig.RemoteConfig `RemoteConfig`} service for the @@ -45,355 +88,21 @@ import { app } from '../firebase-namespace-api'; * app is provided, or the `RemoteConfig` service associated with the provided * app. */ -export declare function remoteConfig(app?: app.App): remoteConfig.RemoteConfig; +export declare function remoteConfig(app?: App): remoteConfig.RemoteConfig; /* eslint-disable @typescript-eslint/no-namespace */ export namespace remoteConfig { - /** - * Interface representing options for Remote Config list versions operation. - */ - export interface ListVersionsOptions { - /** - * The maximum number of items to return per page. - */ - pageSize?: number; - - /** - * The `nextPageToken` value returned from a previous list versions request, if any. - */ - pageToken?: string; - - /** - * Specifies the newest version number to include in the results. - * If specified, must be greater than zero. Defaults to the newest version. - */ - endVersionNumber?: string | number; - - /** - * Specifies the earliest update time to include in the results. Any entries updated before this - * time are omitted. - */ - startTime?: Date | string; - - /** - * Specifies the latest update time to include in the results. Any entries updated on or after - * this time are omitted. - */ - endTime?: Date | string; - } - - /** - * Interface representing a list of Remote Config template versions. - */ - export interface ListVersionsResult { - /** - * A list of version metadata objects, sorted in reverse chronological order. - */ - versions: Version[]; - - /** - * Token to retrieve the next page of results, or empty if there are no more results - * in the list. - */ - nextPageToken?: string; - } - - /** - * Interface representing a Remote Config condition. - * A condition targets a specific group of users. A list of these conditions make up - * part of a Remote Config template. - */ - export interface RemoteConfigCondition { - - /** - * A non-empty and unique name of this condition. - */ - name: string; - - /** - * The logic of this condition. - * See the documentation on - * {@link https://firebase.google.com/docs/remote-config/condition-reference condition expressions} - * for the expected syntax of this field. - */ - expression: string; - - /** - * The color associated with this condition for display purposes in the Firebase Console. - * Not specifying this value results in the console picking an arbitrary color to associate - * with the condition. - */ - tagColor?: TagColor; - } - - /** - * Interface representing a Remote Config parameter. - * At minimum, a `defaultValue` or a `conditionalValues` entry must be present for the - * parameter to have any effect. - */ - export interface RemoteConfigParameter { - - /** - * The value to set the parameter to, when none of the named conditions evaluate to `true`. - */ - defaultValue?: RemoteConfigParameterValue; - - /** - * A `(condition name, value)` map. The condition name of the highest priority - * (the one listed first in the Remote Config template's conditions list) determines the value of - * this parameter. - */ - conditionalValues?: { [key: string]: RemoteConfigParameterValue }; - - /** - * A description for this parameter. Should not be over 100 characters and may contain any - * Unicode characters. - */ - description?: string; - } - - /** - * Interface representing a Remote Config parameter group. - * Grouping parameters is only for management purposes and does not affect client-side - * fetching of parameter values. - */ - export interface RemoteConfigParameterGroup { - /** - * A description for the group. Its length must be less than or equal to 256 characters. - * A description may contain any Unicode characters. - */ - description?: string; - - /** - * Map of parameter keys to their optional default values and optional conditional values for - * parameters that belong to this group. A parameter only appears once per - * Remote Config template. An ungrouped parameter appears at the top level, whereas a - * parameter organized within a group appears within its group's map of parameters. - */ - parameters: { [key: string]: RemoteConfigParameter }; - } - - /** - * Interface representing an explicit parameter value. - */ - export interface ExplicitParameterValue { - /** - * The `string` value that the parameter is set to. - */ - value: string; - } - - /** - * Interface representing an in-app-default value. - */ - export interface InAppDefaultValue { - /** - * If `true`, the parameter is omitted from the parameter values returned to a client. - */ - useInAppDefault: boolean; - } - - /** - * Type representing a Remote Config parameter value. - * A `RemoteConfigParameterValue` could be either an `ExplicitParameterValue` or - * an `InAppDefaultValue`. - */ - export type RemoteConfigParameterValue = ExplicitParameterValue | InAppDefaultValue; - - /** - * Interface representing a Remote Config template. - */ - export interface RemoteConfigTemplate { - /** - * A list of conditions in descending order by priority. - */ - conditions: RemoteConfigCondition[]; - - /** - * Map of parameter keys to their optional default values and optional conditional values. - */ - parameters: { [key: string]: RemoteConfigParameter }; - - /** - * Map of parameter group names to their parameter group objects. - * A group's name is mutable but must be unique among groups in the Remote Config template. - * The name is limited to 256 characters and intended to be human-readable. Any Unicode - * characters are allowed. - */ - parameterGroups: { [key: string]: RemoteConfigParameterGroup }; - - /** - * ETag of the current Remote Config template (readonly). - */ - readonly etag: string; - - /** - * Version information for the current Remote Config template. - */ - version?: Version; - } - - /** - * Interface representing a Remote Config user. - */ - export interface RemoteConfigUser { - /** - * Email address. Output only. - */ - email: string; - - /** - * Display name. Output only. - */ - name?: string; - - /** - * Image URL. Output only. - */ - imageUrl?: string; - } - - /** - * Colors that are associated with conditions for display purposes. - */ - export type TagColor = 'BLUE' | 'BROWN' | 'CYAN' | 'DEEP_ORANGE' | 'GREEN' | - 'INDIGO' | 'LIME' | 'ORANGE' | 'PINK' | 'PURPLE' | 'TEAL'; - - /** - * Interface representing a Remote Config template version. - * Output only, except for the version description. Contains metadata about a particular - * version of the Remote Config template. All fields are set at the time the specified Remote - * Config template is published. A version's description field may be specified in - * `publishTemplate` calls. - */ - export interface Version { - /** - * The version number of a Remote Config template. - */ - versionNumber?: string; - - /** - * The timestamp of when this version of the Remote Config template was written to the - * Remote Config backend. - */ - updateTime?: string; - - /** - * The origin of the template update action. - */ - updateOrigin?: ('REMOTE_CONFIG_UPDATE_ORIGIN_UNSPECIFIED' | 'CONSOLE' | - 'REST_API' | 'ADMIN_SDK_NODE'); - - /** - * The type of the template update action. - */ - updateType?: ('REMOTE_CONFIG_UPDATE_TYPE_UNSPECIFIED' | - 'INCREMENTAL_UPDATE' | 'FORCED_UPDATE' | 'ROLLBACK'); - - /** - * Aggregation of all metadata fields about the account that performed the update. - */ - updateUser?: RemoteConfigUser; - - /** - * The user-provided description of the corresponding Remote Config template. - */ - description?: string; - - /** - * The version number of the Remote Config template that has become the current version - * due to a rollback. Only present if this version is the result of a rollback. - */ - rollbackSource?: string; - - /** - * Indicates whether this Remote Config template was published before version history was - * supported. - */ - isLegacy?: boolean; - } - - /** - * The Firebase `RemoteConfig` service interface. - */ - export interface RemoteConfig { - app: app.App; - - /** - * Gets the current active version of the {@link remoteConfig.RemoteConfigTemplate - * `RemoteConfigTemplate`} of the project. - * - * @return A promise that fulfills with a `RemoteConfigTemplate`. - */ - getTemplate(): Promise; - - /** - * Gets the requested version of the {@link remoteConfig.RemoteConfigTemplate - * `RemoteConfigTemplate`} of the project. - * - * @param versionNumber Version number of the Remote Config template to look up. - * - * @return A promise that fulfills with a `RemoteConfigTemplate`. - */ - getTemplateAtVersion(versionNumber: number | string): Promise; - - /** - * Validates a {@link remoteConfig.RemoteConfigTemplate `RemoteConfigTemplate`}. - * - * @param template The Remote Config template to be validated. - * @returns A promise that fulfills with the validated `RemoteConfigTemplate`. - */ - validateTemplate(template: RemoteConfigTemplate): Promise; - - /** - * Publishes a Remote Config template. - * - * @param template The Remote Config template to be published. - * @param options Optional options object when publishing a Remote Config template: - * - {boolean} `force` Setting this to `true` forces the Remote Config template to - * be updated and circumvent the ETag. This approach is not recommended - * because it risks causing the loss of updates to your Remote Config - * template if multiple clients are updating the Remote Config template. - * See {@link https://firebase.google.com/docs/remote-config/use-config-rest#etag_usage_and_forced_updates - * ETag usage and forced updates}. - * - * @return A Promise that fulfills with the published `RemoteConfigTemplate`. - */ - publishTemplate(template: RemoteConfigTemplate, options?: { force: boolean }): Promise; - - /** - * Rolls back a project's published Remote Config template to the specified version. - * A rollback is equivalent to getting a previously published Remote Config - * template and re-publishing it using a force update. - * - * @param versionNumber The version number of the Remote Config template to roll back to. - * The specified version number must be lower than the current version number, and not have - * been deleted due to staleness. Only the last 300 versions are stored. - * All versions that correspond to non-active Remote Config templates (that is, all except the - * template that is being fetched by clients) are also deleted if they are more than 90 days old. - * @return A promise that fulfills with the published `RemoteConfigTemplate`. - */ - rollback(versionNumber: string | number): Promise; - - /** - * Gets a list of Remote Config template versions that have been published, sorted in reverse - * chronological order. Only the last 300 versions are stored. - * All versions that correspond to non-active Remote Config templates (that is, all except the - * template that is being fetched by clients) are also deleted if they are more than 90 days old. - * - * @param options Optional {@link remoteConfig.ListVersionsOptions `ListVersionsOptions`} - * object for getting a list of template versions. - * @return A promise that fulfills with a `ListVersionsResult`. - */ - listVersions(options?: ListVersionsOptions): Promise; - - /** - * Creates and returns a new Remote Config template from a JSON string. - * - * @param json The JSON string to populate a Remote Config template. - * - * @return A new template instance. - */ - createTemplateFromJSON(json: string): RemoteConfigTemplate; - } + export type ExplicitParameterValue = TExplicitParameterValue; + export type InAppDefaultValue = TInAppDefaultValue; + export type ListVersionsOptions = TListVersionsOptions; + export type ListVersionsResult = TListVersionsResult; + export type RemoteConfig = TRemoteConfig; + export type RemoteConfigCondition = TRemoteConfigCondition; + export type RemoteConfigParameter = TRemoteConfigParameter; + export type RemoteConfigParameterGroup = TRemoteConfigParameterGroup; + export type RemoteConfigParameterValue = TRemoteConfigParameterValue; + export type RemoteConfigTemplate = TRemoteConfigTemplate; + export type RemoteConfigUser = TRemoteConfigUser; + export type TagColor = TTagColor; + export type Version = TVersion; } diff --git a/src/remote-config/remote-config-api-client-internal.ts b/src/remote-config/remote-config-api-client-internal.ts index bb7b5a7eed..1e91b497f3 100644 --- a/src/remote-config/remote-config-api-client-internal.ts +++ b/src/remote-config/remote-config-api-client-internal.ts @@ -14,17 +14,14 @@ * limitations under the License. */ -import { remoteConfig } from './index'; +import { App } from '../app'; +import { FirebaseApp } from '../app/firebase-app'; import { HttpRequestConfig, HttpClient, HttpError, AuthorizedHttpClient, HttpResponse } from '../utils/api-request'; import { PrefixedFirebaseError } from '../utils/error'; -import { FirebaseApp } from '../app/firebase-app'; import * as utils from '../utils/index'; import * as validator from '../utils/validator'; import { deepCopy } from '../utils/deep-copy'; - -import RemoteConfigTemplate = remoteConfig.RemoteConfigTemplate; -import ListVersionsOptions = remoteConfig.ListVersionsOptions; -import ListVersionsResult = remoteConfig.ListVersionsResult; +import { ListVersionsOptions, ListVersionsResult, RemoteConfigTemplate } from './remote-config-api'; // Remote Config backend constants const FIREBASE_REMOTE_CONFIG_V1_API = 'https://firebaseremoteconfig.googleapis.com/v1'; @@ -41,20 +38,20 @@ const FIREBASE_REMOTE_CONFIG_HEADERS = { /** * Class that facilitates sending requests to the Firebase Remote Config backend API. * - * @private + * @internal */ export class RemoteConfigApiClient { private readonly httpClient: HttpClient; private projectIdPrefix?: string; - constructor(private readonly app: FirebaseApp) { + constructor(private readonly app: App) { if (!validator.isNonNullObject(app) || !('options' in app)) { throw new FirebaseRemoteConfigError( 'invalid-argument', 'First argument passed to admin.remoteConfig() must be a valid Firebase app instance.'); } - this.httpClient = new AuthorizedHttpClient(app); + this.httpClient = new AuthorizedHttpClient(app as FirebaseApp); } public getTemplate(): Promise { diff --git a/src/remote-config/remote-config-api.ts b/src/remote-config/remote-config-api.ts new file mode 100644 index 0000000000..9493e855d8 --- /dev/null +++ b/src/remote-config/remote-config-api.ts @@ -0,0 +1,279 @@ +/*! + * Copyright 2021 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. + */ + +/** + * Colors that are associated with conditions for display purposes. + */ +export type TagColor = 'BLUE' | 'BROWN' | 'CYAN' | 'DEEP_ORANGE' | 'GREEN' | + 'INDIGO' | 'LIME' | 'ORANGE' | 'PINK' | 'PURPLE' | 'TEAL'; + +/** + * Interface representing a Remote Config condition. + * A condition targets a specific group of users. A list of these conditions make up + * part of a Remote Config template. + */ +export interface RemoteConfigCondition { + + /** + * A non-empty and unique name of this condition. + */ + name: string; + + /** + * The logic of this condition. + * See the documentation on + * {@link https://firebase.google.com/docs/remote-config/condition-reference condition expressions} + * for the expected syntax of this field. + */ + expression: string; + + /** + * The color associated with this condition for display purposes in the Firebase Console. + * Not specifying this value results in the console picking an arbitrary color to associate + * with the condition. + */ + tagColor?: TagColor; +} + +/** + * Interface representing an explicit parameter value. + */ +export interface ExplicitParameterValue { + /** + * The `string` value that the parameter is set to. + */ + value: string; +} + +/** + * Interface representing an in-app-default value. + */ +export interface InAppDefaultValue { + /** + * If `true`, the parameter is omitted from the parameter values returned to a client. + */ + useInAppDefault: boolean; +} + +/** + * Type representing a Remote Config parameter value. + * A `RemoteConfigParameterValue` could be either an `ExplicitParameterValue` or + * an `InAppDefaultValue`. + */ +export type RemoteConfigParameterValue = ExplicitParameterValue | InAppDefaultValue; + +/** + * Interface representing a Remote Config parameter. + * At minimum, a `defaultValue` or a `conditionalValues` entry must be present for the + * parameter to have any effect. + */ +export interface RemoteConfigParameter { + + /** + * The value to set the parameter to, when none of the named conditions evaluate to `true`. + */ + defaultValue?: RemoteConfigParameterValue; + + /** + * A `(condition name, value)` map. The condition name of the highest priority + * (the one listed first in the Remote Config template's conditions list) determines the value of + * this parameter. + */ + conditionalValues?: { [key: string]: RemoteConfigParameterValue }; + + /** + * A description for this parameter. Should not be over 100 characters and may contain any + * Unicode characters. + */ + description?: string; +} + +/** + * Interface representing a Remote Config parameter group. + * Grouping parameters is only for management purposes and does not affect client-side + * fetching of parameter values. + */ +export interface RemoteConfigParameterGroup { + /** + * A description for the group. Its length must be less than or equal to 256 characters. + * A description may contain any Unicode characters. + */ + description?: string; + + /** + * Map of parameter keys to their optional default values and optional conditional values for + * parameters that belong to this group. A parameter only appears once per + * Remote Config template. An ungrouped parameter appears at the top level, whereas a + * parameter organized within a group appears within its group's map of parameters. + */ + parameters: { [key: string]: RemoteConfigParameter }; +} + +/** + * Interface representing a Remote Config template. + */ +export interface RemoteConfigTemplate { + /** + * A list of conditions in descending order by priority. + */ + conditions: RemoteConfigCondition[]; + + /** + * Map of parameter keys to their optional default values and optional conditional values. + */ + parameters: { [key: string]: RemoteConfigParameter }; + + /** + * Map of parameter group names to their parameter group objects. + * A group's name is mutable but must be unique among groups in the Remote Config template. + * The name is limited to 256 characters and intended to be human-readable. Any Unicode + * characters are allowed. + */ + parameterGroups: { [key: string]: RemoteConfigParameterGroup }; + + /** + * ETag of the current Remote Config template (readonly). + */ + readonly etag: string; + + /** + * Version information for the current Remote Config template. + */ + version?: Version; +} + +/** + * Interface representing a Remote Config user. + */ +export interface RemoteConfigUser { + /** + * Email address. Output only. + */ + email: string; + + /** + * Display name. Output only. + */ + name?: string; + + /** + * Image URL. Output only. + */ + imageUrl?: string; +} + +/** + * Interface representing a Remote Config template version. + * Output only, except for the version description. Contains metadata about a particular + * version of the Remote Config template. All fields are set at the time the specified Remote + * Config template is published. A version's description field may be specified in + * `publishTemplate` calls. + */ +export interface Version { + /** + * The version number of a Remote Config template. + */ + versionNumber?: string; + + /** + * The timestamp of when this version of the Remote Config template was written to the + * Remote Config backend. + */ + updateTime?: string; + + /** + * The origin of the template update action. + */ + updateOrigin?: ('REMOTE_CONFIG_UPDATE_ORIGIN_UNSPECIFIED' | 'CONSOLE' | + 'REST_API' | 'ADMIN_SDK_NODE'); + + /** + * The type of the template update action. + */ + updateType?: ('REMOTE_CONFIG_UPDATE_TYPE_UNSPECIFIED' | + 'INCREMENTAL_UPDATE' | 'FORCED_UPDATE' | 'ROLLBACK'); + + /** + * Aggregation of all metadata fields about the account that performed the update. + */ + updateUser?: RemoteConfigUser; + + /** + * The user-provided description of the corresponding Remote Config template. + */ + description?: string; + + /** + * The version number of the Remote Config template that has become the current version + * due to a rollback. Only present if this version is the result of a rollback. + */ + rollbackSource?: string; + + /** + * Indicates whether this Remote Config template was published before version history was + * supported. + */ + isLegacy?: boolean; +} + +/** + * Interface representing a list of Remote Config template versions. + */ +export interface ListVersionsResult { + /** + * A list of version metadata objects, sorted in reverse chronological order. + */ + versions: Version[]; + + /** + * Token to retrieve the next page of results, or empty if there are no more results + * in the list. + */ + nextPageToken?: string; +} + +/** + * Interface representing options for Remote Config list versions operation. + */ +export interface ListVersionsOptions { + /** + * The maximum number of items to return per page. + */ + pageSize?: number; + + /** + * The `nextPageToken` value returned from a previous list versions request, if any. + */ + pageToken?: string; + + /** + * Specifies the newest version number to include in the results. + * If specified, must be greater than zero. Defaults to the newest version. + */ + endVersionNumber?: string | number; + + /** + * Specifies the earliest update time to include in the results. Any entries updated before this + * time are omitted. + */ + startTime?: Date | string; + + /** + * Specifies the latest update time to include in the results. Any entries updated on or after + * this time are omitted. + */ + endTime?: Date | string; +} diff --git a/src/remote-config/remote-config.ts b/src/remote-config/remote-config.ts index c4f9c9fc03..5f2ce6b252 100644 --- a/src/remote-config/remote-config.ts +++ b/src/remote-config/remote-config.ts @@ -14,33 +14,33 @@ * limitations under the License. */ -import { FirebaseApp } from '../app/firebase-app'; +import { App } from '../app'; import * as validator from '../utils/validator'; -import { remoteConfig } from './index'; import { FirebaseRemoteConfigError, RemoteConfigApiClient } from './remote-config-api-client-internal'; - -import RemoteConfigTemplate = remoteConfig.RemoteConfigTemplate; -import RemoteConfigParameter = remoteConfig.RemoteConfigParameter; -import RemoteConfigCondition = remoteConfig.RemoteConfigCondition; -import RemoteConfigParameterGroup = remoteConfig.RemoteConfigParameterGroup; -import ListVersionsOptions = remoteConfig.ListVersionsOptions; -import ListVersionsResult = remoteConfig.ListVersionsResult; -import RemoteConfigUser = remoteConfig.RemoteConfigUser; -import Version = remoteConfig.Version; -import RemoteConfigInterface = remoteConfig.RemoteConfig; +import { + ListVersionsOptions, + ListVersionsResult, + RemoteConfigCondition, + RemoteConfigParameter, + RemoteConfigParameterGroup, + RemoteConfigTemplate, + RemoteConfigUser, + Version, +} from './remote-config-api'; /** * Remote Config service bound to the provided app. */ -export class RemoteConfig implements RemoteConfigInterface { +export class RemoteConfig { private readonly client: RemoteConfigApiClient; /** * @param app The app for this RemoteConfig service. * @constructor + * @internal */ - constructor(readonly app: FirebaseApp) { + constructor(readonly app: App) { this.client = new RemoteConfigApiClient(app); } diff --git a/test/unit/index.spec.ts b/test/unit/index.spec.ts index f1b5a0d647..07c8e3435b 100644 --- a/test/unit/index.spec.ts +++ b/test/unit/index.spec.ts @@ -76,5 +76,6 @@ import './security-rules/security-rules.spec'; import './security-rules/security-rules-api-client.spec'; // RemoteConfig +import './remote-config/index.spec'; import './remote-config/remote-config.spec'; import './remote-config/remote-config-api-client.spec'; diff --git a/test/unit/remote-config/index.spec.ts b/test/unit/remote-config/index.spec.ts new file mode 100644 index 0000000000..f2fd51a141 --- /dev/null +++ b/test/unit/remote-config/index.spec.ts @@ -0,0 +1,75 @@ +/*! + * @license + * Copyright 2021 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. + */ + +'use strict'; + +import * as chai from 'chai'; +import * as sinonChai from 'sinon-chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +import * as mocks from '../../resources/mocks'; +import { App } from '../../../src/app/index'; +import { getRemoteConfig, RemoteConfig } from '../../../src/remote-config/index'; + +chai.should(); +chai.use(sinonChai); +chai.use(chaiAsPromised); + +const expect = chai.expect; + +describe('RemoteConfig', () => { + let mockApp: App; + let mockCredentialApp: App; + + const noProjectIdError = 'Failed to determine project ID. Initialize the SDK ' + + 'with service account credentials, or set project ID as an app option. Alternatively, set the ' + + 'GOOGLE_CLOUD_PROJECT environment variable.'; + + beforeEach(() => { + mockApp = mocks.app(); + mockCredentialApp = mocks.mockCredentialApp(); + }); + + describe('getRemoteConfig()', () => { + it('should throw when default app is not available', () => { + expect(() => { + return getRemoteConfig(); + }).to.throw('The default Firebase app does not exist.'); + }); + + it('should reject given an invalid credential without project ID', () => { + // Project ID not set in the environment. + delete process.env.GOOGLE_CLOUD_PROJECT; + delete process.env.GCLOUD_PROJECT; + const remoteConfig = getRemoteConfig(mockCredentialApp); + return remoteConfig.getTemplate() + .should.eventually.rejectedWith(noProjectIdError); + }); + + it('should not throw given a valid app', () => { + expect(() => { + return getRemoteConfig(mockApp); + }).not.to.throw(); + }); + + it('should return the same instance for a given app instance', () => { + const rc1: RemoteConfig = getRemoteConfig(mockApp); + const rc2: RemoteConfig = getRemoteConfig(mockApp); + expect(rc1).to.equal(rc2); + }); + }); +}); diff --git a/test/unit/remote-config/remote-config.spec.ts b/test/unit/remote-config/remote-config.spec.ts index 2b25a5b7bc..e2a95aeb47 100644 --- a/test/unit/remote-config/remote-config.spec.ts +++ b/test/unit/remote-config/remote-config.spec.ts @@ -19,21 +19,21 @@ import * as _ from 'lodash'; import * as chai from 'chai'; import * as sinon from 'sinon'; -import { RemoteConfig } from '../../../src/remote-config/remote-config'; +import { + RemoteConfig, + RemoteConfigTemplate, + RemoteConfigCondition, + TagColor, + ListVersionsResult, +} from '../../../src/remote-config/index'; import { FirebaseApp } from '../../../src/app/firebase-app'; import * as mocks from '../../resources/mocks'; -import { remoteConfig } from '../../../src/remote-config/index'; import { FirebaseRemoteConfigError, RemoteConfigApiClient } from '../../../src/remote-config/remote-config-api-client-internal'; import { deepCopy } from '../../../src/utils/deep-copy'; -import RemoteConfigTemplate = remoteConfig.RemoteConfigTemplate; -import RemoteConfigCondition = remoteConfig.RemoteConfigCondition; -import TagColor = remoteConfig.TagColor; -import ListVersionsResult = remoteConfig.ListVersionsResult; - const expect = chai.expect; describe('RemoteConfig', () => {