diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..833efacc4fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- Include `appId` in web app configuration when using the Hosting emulator (#2798). diff --git a/src/fetchWebSetup.ts b/src/fetchWebSetup.ts index d1f12738946..68e5eedf13d 100644 --- a/src/fetchWebSetup.ts +++ b/src/fetchWebSetup.ts @@ -1,7 +1,8 @@ import { Client } from "./apiv2"; import { configstore } from "./configstore"; -import { firebaseApiOrigin } from "./api"; +import { firebaseApiOrigin, hostingApiOrigin } from "./api"; import * as getProjectId from "./getProjectId"; +import { logger } from "./logger"; export interface WebConfig { projectId: string; @@ -14,7 +15,29 @@ export interface WebConfig { messagingSenderId?: string; } +/** + * See + * https://firebase.google.com/docs/reference/hosting/rest/v1beta1/projects.sites#Site + */ +interface Site { + name: string; + defaultUrl: string; + appId?: string; + labels?: Record; + type: "DEFAULT_SITE" | "USER_SITE" | "SITE_UNSPECIFIED"; +} + +interface ListSitesResponse { + sites: Site[]; + nextPageToken: string; +} + const apiClient = new Client({ urlPrefix: firebaseApiOrigin, auth: true, apiVersion: "v1beta1" }); +const hostingApiClient = new Client({ + urlPrefix: hostingApiOrigin, + auth: true, + apiVersion: "v1beta1", +}); const CONFIGSTORE_KEY = "webconfig"; @@ -35,6 +58,24 @@ export function getCachedWebSetup(options: any): WebConfig | undefined { return allConfigs[projectId]; } +/** + * Recursively list all hosting sites for a given project. + */ +async function listAllSites(projectId: string, nextPageToken?: string): Promise { + const queryParams: Record = nextPageToken ? { pageToken: nextPageToken } : {}; + const res = await hostingApiClient.get(`/projects/${projectId}/sites`, { + queryParams, + }); + + const sites = res.body.sites; + if (res.body.nextPageToken) { + const remainder = await listAllSites(projectId, res.body.nextPageToken); + return [...sites, ...remainder]; + } + + return sites; +} + /** * TODO: deprecate this function in favor of `getAppConfig()` in `/src/management/apps.ts` * @param options CLI options. @@ -42,8 +83,29 @@ export function getCachedWebSetup(options: any): WebConfig | undefined { */ export async function fetchWebSetup(options: any): Promise { const projectId = getProjectId(options, false); - const res = await apiClient.get(`/projects/${projectId}/webApps/-/config`); + + // Try to determine the appId from the default Hosting site, if it is linked. + let hostingAppId: string | undefined = undefined; + try { + const sites = await listAllSites(projectId); + const defaultSite = sites.find((s) => s.type === "DEFAULT_SITE"); + if (defaultSite && defaultSite.appId) { + hostingAppId = defaultSite.appId; + } + } catch (e) { + logger.debug("Failed to list hosting sites"); + logger.debug(e); + } + + // Get the web app config for the appId, or use the '-' special value if the appId is not known + const appId = hostingAppId || "-"; + const res = await apiClient.get(`/projects/${projectId}/webApps/${appId}/config`); const config = res.body; + + if (!config.appId && hostingAppId) { + config.appId = hostingAppId; + } + setCachedWebSetup(config.projectId, config); return config; }