diff --git a/src/init/features/dataconnect/index.spec.ts b/src/init/features/dataconnect/index.spec.ts index afec6ecf99e..40a732dd2f5 100644 --- a/src/init/features/dataconnect/index.spec.ts +++ b/src/init/features/dataconnect/index.spec.ts @@ -39,7 +39,7 @@ describe("init dataconnect", () => { requiredInfo: mockRequiredInfo(), config: mockConfig(), expectedSource: "dataconnect", - expectedFiles: ["dataconnect/dataconnect.yaml", "dataconnect/schema/schema.gql"], + expectedFiles: ["dataconnect/dataconnect.yaml"], expectCSQLProvisioning: false, }, { @@ -47,7 +47,22 @@ describe("init dataconnect", () => { requiredInfo: mockRequiredInfo(), config: mockConfig({ dataconnect: { source: "not-dataconnect" } }), expectedSource: "not-dataconnect", - expectedFiles: ["not-dataconnect/dataconnect.yaml", "not-dataconnect/schema/schema.gql"], + expectedFiles: ["not-dataconnect/dataconnect.yaml"], + expectCSQLProvisioning: false, + }, + { + desc: "should write schema files", + requiredInfo: mockRequiredInfo({ + schemaGql: [ + { + path: "schema.gql", + content: "## Fake GQL", + }, + ], + }), + config: mockConfig({}), + expectedSource: "dataconnect", + expectedFiles: ["dataconnect/dataconnect.yaml", "dataconnect/schema/schema.gql"], expectCSQLProvisioning: false, }, { @@ -70,7 +85,6 @@ describe("init dataconnect", () => { expectedSource: "dataconnect", expectedFiles: [ "dataconnect/dataconnect.yaml", - "dataconnect/schema/schema.gql", "dataconnect/hello/connector.yaml", "dataconnect/hello/queries.gql", ], @@ -83,7 +97,7 @@ describe("init dataconnect", () => { }), config: mockConfig({}), expectedSource: "dataconnect", - expectedFiles: ["dataconnect/dataconnect.yaml", "dataconnect/schema/schema.gql"], + expectedFiles: ["dataconnect/dataconnect.yaml"], expectCSQLProvisioning: true, }, ]; diff --git a/src/init/features/dataconnect/index.ts b/src/init/features/dataconnect/index.ts index 56e48ffc2d9..d88d3a9024c 100644 --- a/src/init/features/dataconnect/index.ts +++ b/src/init/features/dataconnect/index.ts @@ -49,6 +49,12 @@ export interface RequiredInfo { shouldProvisionCSQL: boolean; } +const emptyConnector = { + id: "default", + path: "./connector", + files: [], +}; + const defaultConnector = { id: "default", path: "./connector", @@ -64,6 +70,8 @@ const defaultConnector = { ], }; +const defaultSchema = { path: "schema.gql", content: SCHEMA_TEMPLATE }; + // doSetup is split into 2 phases - ask questions and then actuate files and API calls based on those answers. export async function doSetup(setup: Setup, config: Config): Promise { const info = await askQuestions(setup); @@ -77,8 +85,6 @@ export async function doSetup(setup: Setup, config: Config): Promise { `If you'd like to add the generated SDK to your app your later, run ${clc.bold("firebase init dataconnect:sdk")}`, ); } - - logger.info(""); } // askQuestions prompts the user about the Data Connect service they want to init. Any prompting @@ -92,7 +98,7 @@ async function askQuestions(setup: Setup): Promise { cloudSqlDatabase: "", isNewDatabase: false, connectors: [defaultConnector], - schemaGql: [], + schemaGql: [defaultSchema], shouldProvisionCSQL: false, }; const isBillingEnabled = setup.projectId ? await checkBillingEnabled(setup.projectId) : false; @@ -110,7 +116,9 @@ async function askQuestions(setup: Setup): Promise { isBillingEnabled && requiredConfigUnset ? await confirm({ message: `Would you like to configure your backend resources now?`, - default: false, + // For Blaze Projects, configure Cloud SQL by default. + // TODO: For Spark projects, allow them to configure Cloud SQL but deploy as unlinked Postgres. + default: true, }) : false; if (shouldConfigureBackend) { @@ -177,8 +185,6 @@ async function writeFiles(config: Config, info: RequiredInfo) { for (const f of info.schemaGql) { await config.askWriteProjectFile(join(dir, "schema", f.path), f.content); } - } else { - await config.askWriteProjectFile(join(dir, "schema", "schema.gql"), SCHEMA_TEMPLATE); } for (const c of info.connectors) { await writeConnectorFiles(config, c); @@ -278,6 +284,9 @@ async function checkExistingInstances( const serviceName = parseServiceName(choice.service.name); info.serviceId = serviceName.serviceId; info.locationId = serviceName.location; + // If the existing service has no schema, don't override any gql files. + info.schemaGql = []; + info.connectors = [emptyConnector]; if (choice.schema) { const primaryDatasource = choice.schema.datasources.find((d) => d.postgresql); if (primaryDatasource?.postgresql?.cloudSql.instance) { @@ -286,7 +295,7 @@ async function checkExistingInstances( ); info.cloudSqlInstanceId = instanceName.instanceId; } - if (choice.schema.source.files) { + if (choice.schema.source.files?.length) { info.schemaGql = choice.schema.source.files; } info.cloudSqlDatabase = primaryDatasource?.postgresql?.database ?? ""; diff --git a/src/init/features/dataconnect/sdk.spec.ts b/src/init/features/dataconnect/sdk.spec.ts index 0fdd9a2ffc9..54dacae076b 100644 --- a/src/init/features/dataconnect/sdk.spec.ts +++ b/src/init/features/dataconnect/sdk.spec.ts @@ -32,22 +32,17 @@ describe("init dataconnect:sdk", () => { shouldGenerate: boolean; }[] = [ { - desc: "should write files and generate code if shouldGenerate=true", - sdkInfo: mockSDKInfo(true), + desc: "should write files and generate code", + sdkInfo: mockSDKInfo(), shouldGenerate: true, }, - { - desc: "should write files and not generate code if shouldGenerate=false", - sdkInfo: mockSDKInfo(false), - shouldGenerate: false, - }, ]; for (const c of cases) { it(c.desc, async () => { generateStub.resolves(); fsStub.returns({}); - await sdk.actuate(c.sdkInfo, "TEST_PROJECT"); + await sdk.actuate(c.sdkInfo); expect(generateStub.called).to.equal(c.shouldGenerate); expect(fsStub.args).to.deep.equal([ [ @@ -61,7 +56,7 @@ describe("init dataconnect:sdk", () => { }); }); -function mockSDKInfo(shouldGenerate: boolean): sdk.SDKInfo { +function mockSDKInfo(): sdk.SDKInfo { return { connectorYamlContents: CONNECTOR_YAML_CONTENTS, connectorInfo: { @@ -74,7 +69,6 @@ function mockSDKInfo(shouldGenerate: boolean): sdk.SDKInfo { connectorId: "app", }, }, - shouldGenerate, displayIOSWarning: false, }; } diff --git a/src/init/features/dataconnect/sdk.ts b/src/init/features/dataconnect/sdk.ts index 9b854b1c074..69eb0f51a99 100644 --- a/src/init/features/dataconnect/sdk.ts +++ b/src/init/features/dataconnect/sdk.ts @@ -29,14 +29,13 @@ export const FDC_APP_FOLDER = "_FDC_APP_FOLDER"; export type SDKInfo = { connectorYamlContents: string; connectorInfo: ConnectorInfo; - shouldGenerate: boolean; displayIOSWarning: boolean; }; export async function doSetup(setup: Setup, config: Config): Promise { const sdkInfo = await askQuestions(setup, config); - await actuate(sdkInfo, setup.projectId); + await actuate(sdkInfo); logSuccess( - `If you'd like to generate additional SDKs later, run ${clc.bold("firebase init dataconnect:sdk")}`, + `If you'd like to add more generated SDKs to your app your later, run ${clc.bold("firebase init dataconnect:sdk")} again`, ); } @@ -190,30 +189,21 @@ async function askQuestions(setup: Setup, config: Config): Promise { newConnectorYaml.generate.kotlinSdk = kotlinSdk; } - const shouldGenerate = !!( - setup.projectId && - (await confirm({ - message: "Would you like to generate SDK code now?", - default: true, - })) - ); // TODO: Prompt user about adding generated paths to .gitignore const connectorYamlContents = yaml.stringify(newConnectorYaml); connectorInfo.connectorYaml = newConnectorYaml; - return { connectorYamlContents, connectorInfo, shouldGenerate, displayIOSWarning }; + return { connectorYamlContents, connectorInfo, displayIOSWarning }; } -export async function actuate(sdkInfo: SDKInfo, projectId?: string) { +export async function actuate(sdkInfo: SDKInfo) { const connectorYamlPath = `${sdkInfo.connectorInfo.directory}/connector.yaml`; fs.writeFileSync(connectorYamlPath, sdkInfo.connectorYamlContents, "utf8"); logBullet(`Wrote new config to ${connectorYamlPath}`); - if (projectId && sdkInfo.shouldGenerate) { - await DataConnectEmulator.generate({ - configDir: sdkInfo.connectorInfo.directory, - connectorId: sdkInfo.connectorInfo.connectorYaml.connectorId, - }); - logBullet(`Generated SDK code for ${sdkInfo.connectorInfo.connectorYaml.connectorId}`); - } + await DataConnectEmulator.generate({ + configDir: sdkInfo.connectorInfo.directory, + connectorId: sdkInfo.connectorInfo.connectorYaml.connectorId, + }); + logBullet(`Generated SDK code for ${sdkInfo.connectorInfo.connectorYaml.connectorId}`); if (sdkInfo.connectorInfo.connectorYaml.generate?.swiftSdk && sdkInfo.displayIOSWarning) { logBullet( clc.bold(