From 30e8f25c81479ac3acb06e71b9f3b112eb07d550 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Mon, 28 Jul 2025 15:50:18 -0700 Subject: [PATCH 01/10] Good progress on enterprise edition from Gemini plus a helping hand --- src/commands/firestore-databases-create.ts | 5 +++++ src/firestore/api-types.ts | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/commands/firestore-databases-create.ts b/src/commands/firestore-databases-create.ts index 8b218ac1e92..323b65f3b48 100644 --- a/src/commands/firestore-databases-create.ts +++ b/src/commands/firestore-databases-create.ts @@ -17,6 +17,7 @@ export const command = new Command("firestore:databases:create ") "--location ", "region to create database, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations (required)", ) + .option("--enterprise-edition", "create a database with enterprise capabilities") .option( "--delete-protection ", "whether or not to prevent deletion of database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'", @@ -44,6 +45,9 @@ export const command = new Command("firestore:databases:create ") } // Type is always Firestore Native since Firebase does not support Datastore Mode const type: types.DatabaseType = types.DatabaseType.FIRESTORE_NATIVE; + const databaseEdition: types.DatabaseEdition | undefined = options.enterpriseEdition + ? types.DatabaseEdition.ENTERPRISE + : undefined; if ( options.deleteProtection && options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.ENABLED && @@ -82,6 +86,7 @@ export const command = new Command("firestore:databases:create ") databaseId: database, locationId: options.location, type, + databaseEdition, deleteProtectionState, pointInTimeRecoveryEnablement, cmekConfig, diff --git a/src/firestore/api-types.ts b/src/firestore/api-types.ts index 701d7e4097c..b6d941b66b6 100644 --- a/src/firestore/api-types.ts +++ b/src/firestore/api-types.ts @@ -101,6 +101,11 @@ export enum DatabaseType { FIRESTORE_NATIVE = "FIRESTORE_NATIVE", } +export enum DatabaseEdition { + STANDARD = "STANDARD", + ENTERPRISE = "ENTERPRISE", +} + export enum DatabaseDeleteProtectionStateOption { ENABLED = "ENABLED", DISABLED = "DISABLED", @@ -134,6 +139,7 @@ export interface CreateDatabaseReq { databaseId: string; locationId: string; type: DatabaseType; + databaseEdition?: DatabaseEdition; deleteProtectionState: DatabaseDeleteProtectionState; pointInTimeRecoveryEnablement: PointInTimeRecoveryEnablement; cmekConfig?: CmekConfig; @@ -146,6 +152,7 @@ export interface DatabaseResp { updateTime: string; locationId: string; type: DatabaseType; + databaseEdition: DatabaseEdition; concurrencyMode: string; appEngineIntegrationMode: string; keyPrefix: string; From 0ee3697cb690386c48342eb6cf225816aaeac7cb Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Tue, 29 Jul 2025 08:51:50 -0700 Subject: [PATCH 02/10] Added unit test, updated flag to an enum --- .../firestore-databases-create.spec.ts | 255 ++++++++++++++++++ src/commands/firestore-databases-create.ts | 19 +- 2 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 src/commands/firestore-databases-create.spec.ts diff --git a/src/commands/firestore-databases-create.spec.ts b/src/commands/firestore-databases-create.spec.ts new file mode 100644 index 00000000000..f0fb46bb0b3 --- /dev/null +++ b/src/commands/firestore-databases-create.spec.ts @@ -0,0 +1,255 @@ +import * as sinon from "sinon"; +import { expect } from "chai"; +import { Command } from "../command"; +import { command as firestoreDatabasesCreate } from "./firestore-databases-create"; +import * as fsi from "../firestore/api"; +import * as types from "../firestore/api-types"; +import { FirebaseError } from "../error"; + +describe("firestore:databases:create", () => { + const PROJECT = "test-project"; + const DATABASE = "test-database"; + const LOCATION = "nam5"; + + let command: Command; + let firestoreApiStub: sinon.SinonStubbedInstance; + + beforeEach(() => { + command = firestoreDatabasesCreate; + firestoreApiStub = sinon.createStubInstance(fsi.FirestoreApi); + sinon.stub(fsi, "FirestoreApi").returns(firestoreApiStub as any); + }); + + afterEach(() => { + sinon.restore(); + }); + + const mockDatabaseResp = (overrides: Partial): types.DatabaseResp => { + return { + name: `projects/${PROJECT}/databases/${DATABASE}`, + uid: "test-uid", + createTime: "2025-07-28T12:00:00Z", + updateTime: "2025-07-28T12:00:00Z", + locationId: LOCATION, + type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: types.DatabaseEdition.STANDARD, + concurrencyMode: "OPTIMISTIC", + appEngineIntegrationMode: "DISABLED", + keyPrefix: `projects/${PROJECT}/databases/${DATABASE}`, + deleteProtectionState: types.DatabaseDeleteProtectionState.DISABLED, + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.DISABLED, + etag: "test-etag", + versionRetentionPeriod: "1h", + earliestVersionTime: "2025-07-28T11:00:00Z", + ...overrides, + }; + }; + + it("should create a new database with the correct parameters", async () => { + const options = { + project: PROJECT, + location: LOCATION, + json: true, + }; + const expectedDatabase = mockDatabaseResp({}); + firestoreApiStub.createDatabase.resolves(expectedDatabase); + + const result = await command.runner()(DATABASE, options); + + expect(result).to.deep.equal(expectedDatabase); + expect( + firestoreApiStub.createDatabase.calledOnceWith({ + project: PROJECT, + databaseId: DATABASE, + locationId: LOCATION, + type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: types.DatabaseEdition.STANDARD, + deleteProtectionState: types.DatabaseDeleteProtectionState.DISABLED, + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.DISABLED, + cmekConfig: undefined, + }), + ).to.be.true; + }); + + it("should throw an error if location is not provided", async () => { + const options = { + project: PROJECT, + }; + + await expect(command.runner()(DATABASE, options)).to.be.rejectedWith( + FirebaseError, + "Missing required flag --location", + ); + }); + + it("should throw an error for invalid delete protection option", async () => { + const options = { + project: PROJECT, + location: LOCATION, + deleteProtection: "INVALID", + }; + + await expect(command.runner()(DATABASE, options)).to.be.rejectedWith( + FirebaseError, + "Invalid value for flag --delete-protection", + ); + }); + + it("should throw an error for invalid point-in-time recovery option", async () => { + const options = { + project: PROJECT, + location: LOCATION, + pointInTimeRecovery: "INVALID", + }; + + await expect(command.runner()(DATABASE, options)).to.be.rejectedWith( + FirebaseError, + "Invalid value for flag --point-in-time-recovery", + ); + }); + + it("should throw an error for invalid edition option", async () => { + const options = { + project: PROJECT, + location: LOCATION, + edition: "INVALID", + }; + + await expect(command.runner()(DATABASE, options)).to.be.rejectedWith( + FirebaseError, + "Invalid value for flag --edition", + ); + }); + + it("should create a database with enterprise edition", async () => { + const options = { + project: PROJECT, + location: LOCATION, + edition: "enterprise", + json: true, + }; + const expectedDatabase = mockDatabaseResp({ + databaseEdition: types.DatabaseEdition.ENTERPRISE, + }); + firestoreApiStub.createDatabase.resolves(expectedDatabase); + + const result = await command.runner()(DATABASE, options); + + expect(result).to.deep.equal(expectedDatabase); + expect( + firestoreApiStub.createDatabase.calledOnceWith({ + project: PROJECT, + databaseId: DATABASE, + locationId: LOCATION, + type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: types.DatabaseEdition.ENTERPRISE, + deleteProtectionState: types.DatabaseDeleteProtectionState.DISABLED, + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.DISABLED, + cmekConfig: undefined, + }), + ).to.be.true; + }); + + it("should create a database with delete protection enabled", async () => { + const options = { + project: PROJECT, + location: LOCATION, + deleteProtection: "ENABLED", + json: true, + }; + const expectedDatabase = mockDatabaseResp({ + deleteProtectionState: types.DatabaseDeleteProtectionState.ENABLED, + }); + firestoreApiStub.createDatabase.resolves(expectedDatabase); + + const result = await command.runner()(DATABASE, options); + + expect(result).to.deep.equal(expectedDatabase); + expect( + firestoreApiStub.createDatabase.calledOnceWith({ + project: PROJECT, + databaseId: DATABASE, + locationId: LOCATION, + type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: types.DatabaseEdition.STANDARD, + deleteProtectionState: types.DatabaseDeleteProtectionState.ENABLED, + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.DISABLED, + cmekConfig: undefined, + }), + ).to.be.true; + }); + + it("should create a database with point-in-time recovery enabled", async () => { + const options = { + project: PROJECT, + location: LOCATION, + pointInTimeRecovery: "ENABLED", + json: true, + }; + const expectedDatabase = mockDatabaseResp({ + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.ENABLED, + }); + firestoreApiStub.createDatabase.resolves(expectedDatabase); + + const result = await command.runner()(DATABASE, options); + + expect(result).to.deep.equal(expectedDatabase); + expect( + firestoreApiStub.createDatabase.calledOnceWith({ + project: PROJECT, + databaseId: DATABASE, + locationId: LOCATION, + type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: types.DatabaseEdition.STANDARD, + deleteProtectionState: types.DatabaseDeleteProtectionState.DISABLED, + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.ENABLED, + cmekConfig: undefined, + }), + ).to.be.true; + }); + + it("should create a database with a KMS key", async () => { + const KMS_KEY = "test-kms-key"; + const options = { + project: PROJECT, + location: LOCATION, + kmsKeyName: KMS_KEY, + json: true, + }; + const expectedDatabase = mockDatabaseResp({ + cmekConfig: { + kmsKeyName: KMS_KEY, + }, + }); + firestoreApiStub.createDatabase.resolves(expectedDatabase); + + const result = await command.runner()(DATABASE, options); + + expect(result).to.deep.equal(expectedDatabase); + expect( + firestoreApiStub.createDatabase.calledOnceWith({ + project: PROJECT, + databaseId: DATABASE, + locationId: LOCATION, + type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: types.DatabaseEdition.STANDARD, + deleteProtectionState: types.DatabaseDeleteProtectionState.DISABLED, + pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.DISABLED, + cmekConfig: { + kmsKeyName: KMS_KEY, + }, + }), + ).to.be.true; + }); + + it("should throw an error if the API call fails", async () => { + const options = { + project: PROJECT, + location: LOCATION, + }; + const apiError = new Error("API Error"); + firestoreApiStub.createDatabase.rejects(apiError); + + await expect(command.runner()(DATABASE, options)).to.be.rejectedWith(apiError); + }); +}); diff --git a/src/commands/firestore-databases-create.ts b/src/commands/firestore-databases-create.ts index 323b65f3b48..99677baaf40 100644 --- a/src/commands/firestore-databases-create.ts +++ b/src/commands/firestore-databases-create.ts @@ -17,7 +17,10 @@ export const command = new Command("firestore:databases:create ") "--location ", "region to create database, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations (required)", ) - .option("--enterprise-edition", "create a database with enterprise capabilities") + .option( + "--edition ", + "the edition of the database to create, for example 'standard' or 'enterprise'. If not provided, 'standard' is used as a default.", + ) .option( "--delete-protection ", "whether or not to prevent deletion of database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'", @@ -45,9 +48,17 @@ export const command = new Command("firestore:databases:create ") } // Type is always Firestore Native since Firebase does not support Datastore Mode const type: types.DatabaseType = types.DatabaseType.FIRESTORE_NATIVE; - const databaseEdition: types.DatabaseEdition | undefined = options.enterpriseEdition - ? types.DatabaseEdition.ENTERPRISE - : undefined; + if (options.edition && + options.edition !== "standard" && + options.edition !== "enterprise" + ) { + throw new FirebaseError(`Invalid value for flag --edition. ${helpCommandText}`); + } + const databaseEdition: types.DatabaseEdition = + options.edition === "enterprise" + ? types.DatabaseEdition.ENTERPRISE + : types.DatabaseEdition.STANDARD; + if ( options.deleteProtection && options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.ENABLED && From 12a0cfbe81fae21e51f6d8582ca25ae7bfb12fda Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 7 Aug 2025 15:07:52 -0700 Subject: [PATCH 03/10] minor fixups. --- .../firestore-databases-create.spec.ts | 2 +- src/commands/firestore-databases-create.ts | 26 ++++++++++++------- src/firestore/api-types.ts | 1 + src/firestore/api.ts | 1 + src/firestore/options.ts | 1 + 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/commands/firestore-databases-create.spec.ts b/src/commands/firestore-databases-create.spec.ts index f0fb46bb0b3..e8f18ddd0bb 100644 --- a/src/commands/firestore-databases-create.spec.ts +++ b/src/commands/firestore-databases-create.spec.ts @@ -17,7 +17,7 @@ describe("firestore:databases:create", () => { beforeEach(() => { command = firestoreDatabasesCreate; firestoreApiStub = sinon.createStubInstance(fsi.FirestoreApi); - sinon.stub(fsi, "FirestoreApi").returns(firestoreApiStub as any); + sinon.stub(fsi, "FirestoreApi").returns(firestoreApiStub); }); afterEach(() => { diff --git a/src/commands/firestore-databases-create.ts b/src/commands/firestore-databases-create.ts index 99677baaf40..ffed044ac87 100644 --- a/src/commands/firestore-databases-create.ts +++ b/src/commands/firestore-databases-create.ts @@ -48,17 +48,23 @@ export const command = new Command("firestore:databases:create ") } // Type is always Firestore Native since Firebase does not support Datastore Mode const type: types.DatabaseType = types.DatabaseType.FIRESTORE_NATIVE; - if (options.edition && - options.edition !== "standard" && - options.edition !== "enterprise" - ) { - throw new FirebaseError(`Invalid value for flag --edition. ${helpCommandText}`); + + // Figure out the database edition. + let databaseEdition: types.DatabaseEdition = types.DatabaseEdition.STANDARD; + if (options.edition) { + const edition = options.edition.toUpperCase(); + if ( + edition !== types.DatabaseEdition.STANDARD && + edition !== types.DatabaseEdition.ENTERPRISE + ) { + throw new FirebaseError(`Invalid value for flag --edition. ${helpCommandText}`); + } + databaseEdition = + edition === types.DatabaseEdition.ENTERPRISE + ? types.DatabaseEdition.ENTERPRISE + : types.DatabaseEdition.STANDARD; } - const databaseEdition: types.DatabaseEdition = - options.edition === "enterprise" - ? types.DatabaseEdition.ENTERPRISE - : types.DatabaseEdition.STANDARD; - + if ( options.deleteProtection && options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.ENABLED && diff --git a/src/firestore/api-types.ts b/src/firestore/api-types.ts index b6d941b66b6..530cac124d2 100644 --- a/src/firestore/api-types.ts +++ b/src/firestore/api-types.ts @@ -129,6 +129,7 @@ export enum PointInTimeRecoveryEnablement { export interface DatabaseReq { locationId?: string; type?: DatabaseType; + databaseEdition?: DatabaseEdition; deleteProtectionState?: DatabaseDeleteProtectionState; pointInTimeRecoveryEnablement?: PointInTimeRecoveryEnablement; cmekConfig?: CmekConfig; diff --git a/src/firestore/api.ts b/src/firestore/api.ts index 1e8b147a41f..a58a131133d 100644 --- a/src/firestore/api.ts +++ b/src/firestore/api.ts @@ -638,6 +638,7 @@ export class FirestoreApi { const payload: types.DatabaseReq = { locationId: req.locationId, type: req.type, + databaseEdition: req.databaseEdition, deleteProtectionState: req.deleteProtectionState, pointInTimeRecoveryEnablement: req.pointInTimeRecoveryEnablement, cmekConfig: req.cmekConfig, diff --git a/src/firestore/options.ts b/src/firestore/options.ts index 568c50540d2..99024df0269 100644 --- a/src/firestore/options.ts +++ b/src/firestore/options.ts @@ -18,6 +18,7 @@ export interface FirestoreOptions extends Options { type?: types.DatabaseType; deleteProtection?: types.DatabaseDeleteProtectionStateOption; pointInTimeRecoveryEnablement?: types.PointInTimeRecoveryEnablementOption; + edition?: string; // backup schedules backupSchedule?: string; From c6248c017405301485082a7dac50e526fee30423 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 7 Aug 2025 15:40:19 -0700 Subject: [PATCH 04/10] Pick up the edition from firebase.json as well. --- src/deploy/firestore/deploy.ts | 20 ++++++++++++++++++++ src/firebaseConfig.ts | 1 + 2 files changed, 21 insertions(+) diff --git a/src/deploy/firestore/deploy.ts b/src/deploy/firestore/deploy.ts index 5883b38ea5d..9ba5dd53d91 100644 --- a/src/deploy/firestore/deploy.ts +++ b/src/deploy/firestore/deploy.ts @@ -25,6 +25,25 @@ async function createDatabase(context: any, options: Options): Promise { if (!firestoreCfg.database) { firestoreCfg.database = "(default)"; } + + let edition: types.DatabaseEdition = types.DatabaseEdition.STANDARD; + if (!firestoreCfg.edition) { + edition = types.DatabaseEdition.STANDARD; + } else { + if ( + firestoreCfg.edition !== types.DatabaseEdition.STANDARD && + firestoreCfg.edition !== types.DatabaseEdition.ENTERPRISE + ) { + throw new FirebaseError( + `Invalid edition specified for database in firebase.json: ${firestoreCfg.edition}`, + ); + } + edition = + firestoreCfg.edition.toUpperCase() === types.DatabaseEdition.ENTERPRISE + ? types.DatabaseEdition.ENTERPRISE + : types.DatabaseEdition.STANDARD; + } + const api = new FirestoreApi(); try { await api.getDatabase(options.projectId, firestoreCfg.database); @@ -40,6 +59,7 @@ async function createDatabase(context: any, options: Options): Promise { databaseId: firestoreCfg.database, locationId: firestoreCfg.location || "nam5", // Default to 'nam5' if location is not specified type: types.DatabaseType.FIRESTORE_NATIVE, + databaseEdition: edition, deleteProtectionState: types.DatabaseDeleteProtectionState.DISABLED, pointInTimeRecoveryEnablement: types.PointInTimeRecoveryEnablement.DISABLED, }; diff --git a/src/firebaseConfig.ts b/src/firebaseConfig.ts index b0c46bee651..dbffa8e335f 100644 --- a/src/firebaseConfig.ts +++ b/src/firebaseConfig.ts @@ -39,6 +39,7 @@ type DatabaseMultiple = ({ type FirestoreSingle = { database?: string; location?: string; + edition?: string; rules?: string; indexes?: string; } & Deployable; From f009180009f5a92ff8be99d6b3533e8305aa137f Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 7 Aug 2025 16:02:32 -0700 Subject: [PATCH 05/10] Add the database edition to firebase-config.json --- schema/firebase-config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schema/firebase-config.json b/schema/firebase-config.json index 9eb0f6a618f..517f12ca713 100644 --- a/schema/firebase-config.json +++ b/schema/firebase-config.json @@ -88,6 +88,9 @@ "database": { "type": "string" }, + "edition": { + "type": "string" + }, "indexes": { "type": "string" }, From 3264ffd49be62dfd0ec956d158d44874b77a1983 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 7 Aug 2025 16:17:53 -0700 Subject: [PATCH 06/10] requireAuthStub in test. --- src/commands/firestore-databases-create.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/commands/firestore-databases-create.spec.ts b/src/commands/firestore-databases-create.spec.ts index e8f18ddd0bb..8e6231890e5 100644 --- a/src/commands/firestore-databases-create.spec.ts +++ b/src/commands/firestore-databases-create.spec.ts @@ -5,6 +5,7 @@ import { command as firestoreDatabasesCreate } from "./firestore-databases-creat import * as fsi from "../firestore/api"; import * as types from "../firestore/api-types"; import { FirebaseError } from "../error"; +import * as requireAuthModule from "../requireAuth"; describe("firestore:databases:create", () => { const PROJECT = "test-project"; @@ -13,11 +14,14 @@ describe("firestore:databases:create", () => { let command: Command; let firestoreApiStub: sinon.SinonStubbedInstance; + let requireAuthStub: sinon.SinonStub; beforeEach(() => { command = firestoreDatabasesCreate; firestoreApiStub = sinon.createStubInstance(fsi.FirestoreApi); + requireAuthStub = sinon.stub(requireAuthModule, "requireAuth"); sinon.stub(fsi, "FirestoreApi").returns(firestoreApiStub); + requireAuthStub.resolves("a@b.com"); }); afterEach(() => { From 4fd98f9b5336f13a720901abdbe313605bbad6b2 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 7 Aug 2025 16:33:06 -0700 Subject: [PATCH 07/10] fix merge conflicts. --- src/firestore/api-types.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/firestore/api-types.ts b/src/firestore/api-types.ts index dc255964011..f5c21678fa5 100644 --- a/src/firestore/api-types.ts +++ b/src/firestore/api-types.ts @@ -101,11 +101,6 @@ export enum DatabaseType { FIRESTORE_NATIVE = "FIRESTORE_NATIVE", } -export enum DatabaseEdition { - STANDARD = "STANDARD", - ENTERPRISE = "ENTERPRISE", -} - export enum DatabaseDeleteProtectionStateOption { ENABLED = "ENABLED", DISABLED = "DISABLED", @@ -159,7 +154,6 @@ export interface DatabaseResp { updateTime: string; locationId: string; type: DatabaseType; - databaseEdition: DatabaseEdition; concurrencyMode: string; appEngineIntegrationMode: string; keyPrefix: string; From d6b18a86651d0272a1185bdbd1a1afce029f3691 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Thu, 7 Aug 2025 17:06:44 -0700 Subject: [PATCH 08/10] Address feedback. --- src/commands/firestore-databases-create.ts | 5 +---- src/deploy/firestore/deploy.ts | 14 +++++--------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/commands/firestore-databases-create.ts b/src/commands/firestore-databases-create.ts index ffed044ac87..632d8c66fd4 100644 --- a/src/commands/firestore-databases-create.ts +++ b/src/commands/firestore-databases-create.ts @@ -59,10 +59,7 @@ export const command = new Command("firestore:databases:create ") ) { throw new FirebaseError(`Invalid value for flag --edition. ${helpCommandText}`); } - databaseEdition = - edition === types.DatabaseEdition.ENTERPRISE - ? types.DatabaseEdition.ENTERPRISE - : types.DatabaseEdition.STANDARD; + databaseEdition = edition as types.DatabaseEdition; } if ( diff --git a/src/deploy/firestore/deploy.ts b/src/deploy/firestore/deploy.ts index 9ba5dd53d91..317434f0434 100644 --- a/src/deploy/firestore/deploy.ts +++ b/src/deploy/firestore/deploy.ts @@ -27,21 +27,17 @@ async function createDatabase(context: any, options: Options): Promise { } let edition: types.DatabaseEdition = types.DatabaseEdition.STANDARD; - if (!firestoreCfg.edition) { - edition = types.DatabaseEdition.STANDARD; - } else { + if (firestoreCfg.edition) { + const upperEdition = firestoreCfg.edition.toUpperCase(); if ( - firestoreCfg.edition !== types.DatabaseEdition.STANDARD && - firestoreCfg.edition !== types.DatabaseEdition.ENTERPRISE + upperEdition !== types.DatabaseEdition.STANDARD && + upperEdition !== types.DatabaseEdition.ENTERPRISE ) { throw new FirebaseError( `Invalid edition specified for database in firebase.json: ${firestoreCfg.edition}`, ); } - edition = - firestoreCfg.edition.toUpperCase() === types.DatabaseEdition.ENTERPRISE - ? types.DatabaseEdition.ENTERPRISE - : types.DatabaseEdition.STANDARD; + edition = upperEdition as types.DatabaseEdition; } const api = new FirestoreApi(); From 107a9379fd1f439685877052020d892327da06db Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Fri, 8 Aug 2025 14:42:34 -0700 Subject: [PATCH 09/10] Add changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..5cf9b2e3177 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- [Added] Support for creating Firestore Enterprise databases using `firestore:databases:create --edition enterprise`. (#8952) From 47dba1822ea6e641d81277fe2e87e8bec300bb3d Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Tue, 12 Aug 2025 13:11:02 -0700 Subject: [PATCH 10/10] Prettier. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 503fdf1560f..4b7d2d46607 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,2 @@ - [Added] Support for creating Firestore Enterprise databases using `firestore:databases:create --edition enterprise`. (#8952) -- [Added] Support for Firestore Enterprise database index configurations. (#8939) \ No newline at end of file +- [Added] Support for Firestore Enterprise database index configurations. (#8939)