Skip to content

Commit

Permalink
feat: Add internal multi-db support (#1761)
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-andersen committed Sep 30, 2022
1 parent 07181e2 commit 5ba8df0
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
28 changes: 27 additions & 1 deletion dev/src/index.ts
Expand Up @@ -444,6 +444,14 @@ export class Firestore implements firestore.Firestore {
*/
private _projectId: string | undefined = undefined;

/**
* The database ID provided via `.settings()`.
*
* @private
* @internal
*/
private _databaseId: string | undefined = undefined;

/**
* Count of listeners that have been registered on the client.
*
Expand Down Expand Up @@ -612,6 +620,9 @@ export class Firestore implements firestore.Firestore {
settings(settings: firestore.Settings): void {
validateObject('settings', settings);
validateString('settings.projectId', settings.projectId, {optional: true});
validateString('settings.databaseId', settings.databaseId, {
optional: true,
});

if (this._settingsFrozen) {
throw new Error(
Expand All @@ -632,6 +643,11 @@ export class Firestore implements firestore.Firestore {
this._projectId = settings.projectId;
}

if (settings.databaseId !== undefined) {
validateString('settings.databaseId', settings.databaseId);
this._databaseId = settings.databaseId;
}

let url: URL | null = null;

// If the environment variable is set, it should always take precedence
Expand Down Expand Up @@ -719,6 +735,16 @@ export class Firestore implements firestore.Firestore {
return this._projectId;
}

/**
* Returns the Database ID for this Firestore instance.
*
* @private
* @internal
*/
get databaseId(): string {
return this._databaseId || DEFAULT_DATABASE_ID;
}

/**
* Returns the root path of the database. Validates that
* `initializeIfNeeded()` was called before.
Expand All @@ -727,7 +753,7 @@ export class Firestore implements firestore.Firestore {
* @internal
*/
get formattedName(): string {
return `projects/${this.projectId}/databases/${DEFAULT_DATABASE_ID}`;
return `projects/${this.projectId}/databases/${this.databaseId}`;
}

/**
Expand Down
41 changes: 37 additions & 4 deletions dev/test/index.ts
Expand Up @@ -304,6 +304,7 @@ describe('instantiation', () => {

/* eslint-disable @typescript-eslint/no-explicit-any */
expect((firestore as any)._settings.projectId).to.equal(PROJECT_ID);
expect((firestore as any)._settings.databaseId).to.be.undefined;
expect((firestore as any)._settings.foo).to.equal('bar');
/* eslint-enable @typescript-eslint/no-explicit-any */
});
Expand Down Expand Up @@ -343,6 +344,23 @@ describe('instantiation', () => {
);
});

it('validates database ID is string', () => {
expect(() => {
const settings = {...DEFAULT_SETTINGS, databaseId: 1337};
new Firestore.Firestore(settings as InvalidApiUsage);
}).to.throw(
'Value for argument "settings.databaseId" is not a valid string.'
);

expect(() => {
new Firestore.Firestore(DEFAULT_SETTINGS).settings({
databaseId: 1337,
} as InvalidApiUsage);
}).to.throw(
'Value for argument "settings.databaseId" is not a valid string.'
);
});

it('validates ssl is a boolean', () => {
const invalidValues = ['true', 1337];

Expand Down Expand Up @@ -548,11 +566,14 @@ describe('instantiation', () => {
new Firestore.Firestore({maxIdleChannels: 1});
});

it('uses project id from constructor', () => {
const firestore = new Firestore.Firestore({projectId: 'foo'});
it('uses project id and database id from constructor', () => {
const firestore = new Firestore.Firestore({
projectId: 'foo',
databaseId: 'bar',
});

return expect(firestore.formattedName).to.equal(
'projects/foo/databases/(default)'
'projects/foo/databases/bar'
);
});

Expand All @@ -571,7 +592,7 @@ describe('instantiation', () => {
});
});

it('uses project ID from settings()', () => {
it('uses project ID from settings() and default database ID', () => {
const firestore = new Firestore.Firestore({
sslCreds: grpc.credentials.createInsecure(),
});
Expand All @@ -583,6 +604,18 @@ describe('instantiation', () => {
);
});

it('uses database ID and database ID from settings()', () => {
const firestore = new Firestore.Firestore({
sslCreds: grpc.credentials.createInsecure(),
});

firestore.settings({projectId: PROJECT_ID, databaseId: 'bar'});

expect(firestore.formattedName).to.equal(
`projects/${PROJECT_ID}/databases/bar`
);
});

it('handles error from project ID detection', () => {
return createInstance(
{
Expand Down
7 changes: 7 additions & 0 deletions types/firestore.d.ts
Expand Up @@ -227,6 +227,13 @@ declare namespace FirebaseFirestore {
*/
projectId?: string;

/**
* The database name. If omitted, the default database will be used.
*
* @internal
*/
databaseId?: string;

/** The hostname to connect to. */
host?: string;

Expand Down

0 comments on commit 5ba8df0

Please sign in to comment.