diff --git a/src/config.ts b/src/config.ts index 9c23d2d84ae..75fedee9bbc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -229,7 +229,7 @@ export class Config { fs.removeSync(this.path(p)); } - askWriteProjectFile(p: string, content: any, force?: boolean) { + askWriteProjectFile(p: string, content: any, force?: boolean, confirmByDefault?: boolean) { const writeTo = this.path(p); let next; if (typeof content !== "string") { @@ -243,7 +243,7 @@ export class Config { next = promptOnce({ type: "confirm", message: "File " + clc.underline(p) + " already exists. Overwrite?", - default: false, + default: !!confirmByDefault, }); } else { next = Promise.resolve(true); diff --git a/src/dataconnect/freeTrial.ts b/src/dataconnect/freeTrial.ts index 9585dfec2d4..c4d3841defb 100644 --- a/src/dataconnect/freeTrial.ts +++ b/src/dataconnect/freeTrial.ts @@ -67,12 +67,9 @@ export function printFreeTrialUnavailable( } export function upgradeInstructions(projectId: string): string { - return `If you'd like to provision a CloudSQL instance on the Firebase Data Connect no-cost trial: -1. Please upgrade to the pay-as-you-go (Blaze) billing plan. + return `If you'd like to provision a CloudSQL Postgres instance on the Firebase Data Connect no-cost trial: +1. Please upgrade to the pay-as-you-go (Blaze) billing plan. Visit the following page: + https://console.firebase.google.com/project/${projectId}/usage/details 2. Run ${clc.bold("firebase init dataconnect")} again to configure the Cloud SQL instance. -3. Run ${clc.bold("firebase deploy --only dataconnect")} to deploy your Data Connect service. - -To upgrade your project, visit the following URL: - -https://console.firebase.google.com/project/${projectId}/usage/details`; +3. Run ${clc.bold("firebase deploy --only dataconnect")} to deploy your Data Connect service.`; } diff --git a/src/deploy/dataconnect/prepare.ts b/src/deploy/dataconnect/prepare.ts index 7c6b329af90..42e357b2e99 100644 --- a/src/deploy/dataconnect/prepare.ts +++ b/src/deploy/dataconnect/prepare.ts @@ -27,6 +27,9 @@ import { upgradeInstructions } from "../../dataconnect/freeTrial"; */ export default async function (context: any, options: DeployOptions): Promise { const projectId = needProjectId(options); + if (!(await checkBillingEnabled(projectId))) { + throw new FirebaseError(upgradeInstructions(projectId)); + } await ensureApis(projectId); await requireTosAcceptance(DATA_CONNECT_TOS_ID)(options); const serviceCfgs = readFirebaseJson(options.config); @@ -61,9 +64,6 @@ export default async function (context: any, options: DeployOptions): Promise { - const info = await askQuestions(setup); + const isBillingEnabled = setup.projectId ? await checkBillingEnabled(setup.projectId) : false; + if (setup.projectId) { + isBillingEnabled ? await ensureApis(setup.projectId) : await ensureSparkApis(setup.projectId); + } + const info = await askQuestions(setup, isBillingEnabled); await actuate(setup, config, info); const cwdPlatformGuess = await getPlatformFromFolder(process.cwd()); @@ -82,14 +86,17 @@ export async function doSetup(setup: Setup, config: Config): Promise { await sdk.doSetup(setup, config); } else { logBullet( - `If you'd like to add the generated SDK to your app your later, run ${clc.bold("firebase init dataconnect:sdk")}`, + `If you'd like to add the generated SDK to your app your, run ${clc.bold("firebase init dataconnect:sdk")}`, ); } + if (setup.projectId && !isBillingEnabled) { + logBullet(upgradeInstructions(setup.projectId)); + } } // askQuestions prompts the user about the Data Connect service they want to init. Any prompting // logic should live here, and _no_ actuation logic should live here. -async function askQuestions(setup: Setup): Promise { +async function askQuestions(setup: Setup, isBillingEnabled: boolean): Promise { let info: RequiredInfo = { serviceId: "", locationId: "", @@ -101,10 +108,6 @@ async function askQuestions(setup: Setup): Promise { schemaGql: [defaultSchema], shouldProvisionCSQL: false, }; - const isBillingEnabled = setup.projectId ? await checkBillingEnabled(setup.projectId) : false; - if (setup.projectId) { - isBillingEnabled ? await ensureApis(setup.projectId) : await ensureSparkApis(setup.projectId); - } // Query backend and pick up any existing services quickly. info = await promptForExistingServices(setup, info, isBillingEnabled); @@ -136,19 +139,11 @@ async function askQuestions(setup: Setup): Promise { })) ); } else { - if (requiredConfigUnset) { - logBullet( - `Setting placeholder values in dataconnect.yaml. You can edit these before you deploy to specify different IDs or regions.`, - ); - } info.serviceId = info.serviceId || basename(process.cwd()); info.cloudSqlInstanceId = info.cloudSqlInstanceId || `${info.serviceId || "app"}-fdc`; info.locationId = info.locationId || `us-central1`; info.cloudSqlDatabase = info.cloudSqlDatabase || `fdcdb`; } - if (!isBillingEnabled && setup.projectId) { - logBullet(upgradeInstructions(setup.projectId)); - } return info; } @@ -178,12 +173,16 @@ async function writeFiles(config: Config, info: RequiredInfo) { }); config.set("dataconnect", { source: dir }); - await config.askWriteProjectFile(join(dir, "dataconnect.yaml"), subbedDataconnectYaml); + await config.askWriteProjectFile( + join(dir, "dataconnect.yaml"), + subbedDataconnectYaml, + false, + // Default to override dataconnect.yaml + // Sole purpose of `firebase init dataconnect` is to update `dataconnect.yaml`. + true, + ); if (info.schemaGql.length) { - logSuccess( - "The service you chose already has GQL files deployed. We'll use those instead of the default templates.", - ); for (const f of info.schemaGql) { await config.askWriteProjectFile(join(dir, "schema", f.path), f.content); }