Skip to content

Commit 5cd2930

Browse files
committed
Backtrack to previous state
1 parent 118191b commit 5cd2930

File tree

4 files changed

+69
-99
lines changed

4 files changed

+69
-99
lines changed

packages/database/src/api/Database.ts

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { validateUrl } from '../core/util/validation';
2626
import { FirebaseApp } from '@firebase/app-types';
2727
import { FirebaseService } from '@firebase/app-types/private';
2828
import { RepoInfo } from '../core/RepoInfo';
29-
import { AuthTokenProvider } from '../core/AuthTokenProvider';
29+
import { FirebaseDatabase } from '@firebase/database-types';
3030

3131
/**
3232
* Class representing a firebase database.
@@ -35,8 +35,11 @@ import { AuthTokenProvider } from '../core/AuthTokenProvider';
3535
export class Database implements FirebaseService {
3636
INTERNAL: DatabaseInternals;
3737

38-
private repoInternal_?: Repo;
39-
private rootInternal_?: Reference;
38+
/** Track if the instance has been used (root or repo accessed) */
39+
private instanceUsed_: boolean = false;
40+
41+
/** Backing state for root_ */
42+
private rootInternal_: Reference;
4043

4144
static readonly ServerValue = {
4245
TIMESTAMP: {
@@ -53,53 +56,45 @@ export class Database implements FirebaseService {
5356

5457
/**
5558
* The constructor should not be called by users of our public API.
59+
* @param {!Repo} repoInternal_
5660
*/
57-
constructor(
58-
private repoInfo_: RepoInfo,
59-
readonly app: FirebaseApp,
60-
private readonly authTokenProvider_: AuthTokenProvider
61-
) {
62-
if (!(repoInfo_ instanceof RepoInfo)) {
61+
constructor(private repoInternal_: Repo) {
62+
if (!(repoInternal_ instanceof Repo)) {
6363
fatal(
64-
"Don't call new Database() directly please use firebase.database()."
64+
"Don't call new Database() directly - please use firebase.database()."
6565
);
6666
}
67-
68-
// We have to "reserve" the repo now so we can safely create it as-needed
69-
// TOOD(samstern): Enabling this is a mess
70-
// RepoManager.getInstance().reserveRepo(repoInfo_, app);
67+
68+
this.repo_ = repoInternal_;
7169
this.INTERNAL = new DatabaseInternals(this);
7270
}
7371

74-
private get repo_() {
75-
if (!this.repoInternal_) {
76-
this.repoInternal_ = RepoManager.getInstance().createRepo(
77-
this.repoInfo_,
78-
this.app,
79-
this.authTokenProvider_,
80-
this
81-
);
82-
}
72+
private get repo_(): Repo {
73+
this.instanceUsed_ = true;
8374
return this.repoInternal_;
8475
}
85-
76+
8677
private set repo_(repo: Repo) {
78+
if (repo instanceof Repo) {
79+
this.root_ = new Reference(repo, Path.Empty);
80+
}
81+
8782
this.repoInternal_ = repo;
88-
this.rootInternal_ = null;
8983
}
9084

91-
private get root_() {
92-
if (!this.rootInternal_) {
93-
this.rootInternal_ = new Reference(this.repo_, Path.Empty);
94-
}
95-
85+
get root_(): Reference {
86+
this.instanceUsed_ = true;
9687
return this.rootInternal_;
9788
}
9889

99-
private set root_(root: Reference) {
90+
set root_(root: Reference) {
10091
this.rootInternal_ = root;
10192
}
102-
93+
94+
get app(): FirebaseApp {
95+
return this.repo_.app;
96+
}
97+
10398
/**
10499
* Modify this instance to communicate with the Realtime Database emulator.
105100
*
@@ -109,17 +104,19 @@ export class Database implements FirebaseService {
109104
* @param port the emulator port (ex: 8080)
110105
*/
111106
useEmulator(host: string, port: number): void {
112-
if (this.repoInternal_) {
107+
if (this.instanceUsed_) {
113108
fatal(
114109
'Cannot call useEmulator() after instance has already been initialized.'
115110
);
116111
return;
117112
}
118113

119-
const url = `http://${host}:${port}?ns=${this.repoInfo_.namespace}`;
120-
const { repoInfo } = parseRepoInfo(url, this.repoInfo_.nodeAdmin);
114+
// Get a new Repo which has the emulator settings applied
115+
const manager = RepoManager.getInstance();
116+
const oldRepo = this.repo_;
121117

122-
this.repoInfo_ = repoInfo;
118+
this.repo_ = manager.cloneRepoForEmulator(oldRepo, host, port);
119+
manager.deleteRepo(oldRepo);
123120
}
124121

125122
/**
@@ -180,7 +177,7 @@ export class Database implements FirebaseService {
180177
* @param {string} apiName
181178
*/
182179
private checkDeleted_(apiName: string) {
183-
if (this.INTERNAL === null) {
180+
if (this.repo_ === null) {
184181
fatal('Cannot call ' + apiName + ' on a deleted database.');
185182
}
186183
}

packages/database/src/api/Reference.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { validateArgCount, validateCallback, Deferred } from '@firebase/util';
3737
import { SyncPoint } from '../core/SyncPoint';
3838
import { Database } from './Database';
3939
import { DataSnapshot } from './DataSnapshot';
40+
import * as types from '@firebase/database-types';
4041

4142
export interface ReferenceConstructor {
4243
new (repo: Repo, path: Path): Reference;

packages/database/src/core/Repo.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export class Repo {
7171
private interceptServerDataCallback_:
7272
| ((a: string, b: unknown) => void)
7373
| null = null;
74+
private __database: Database;
7475

7576
/** A list of data pieces and paths to be set when this client disconnects. */
7677
private onDisconnect_ = new SparseSnapshotTree();
@@ -82,8 +83,7 @@ export class Repo {
8283
public repoInfo_: RepoInfo,
8384
forceRestClient: boolean,
8485
public app: FirebaseApp,
85-
public authTokenProvider: AuthTokenProvider,
86-
public readonly database: Database,
86+
public authTokenProvider: AuthTokenProvider
8787
) {
8888
this.stats_ = StatsManager.getCollection(repoInfo_);
8989

@@ -637,4 +637,8 @@ export class Repo {
637637
});
638638
}
639639
}
640+
641+
get database(): Database {
642+
return this.__database || (this.__database = new Database(this));
643+
}
640644
}

packages/database/src/core/RepoManager.ts

Lines changed: 28 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class RepoManager {
5353
*/
5454
private repos_: {
5555
[appName: string]: {
56-
[dbUrl: string]: Repo | null;
56+
[dbUrl: string]: Repo;
5757
};
5858
} = {};
5959

@@ -74,25 +74,34 @@ export class RepoManager {
7474
interrupt() {
7575
for (const appName of Object.keys(this.repos_)) {
7676
for (const dbUrl of Object.keys(this.repos_[appName])) {
77-
const repo = this.repos_[appName][dbUrl];
78-
if (repo) {
79-
repo.interrupt();
80-
}
77+
this.repos_[appName][dbUrl].interrupt();
8178
}
8279
}
8380
}
8481

8582
resume() {
8683
for (const appName of Object.keys(this.repos_)) {
8784
for (const dbUrl of Object.keys(this.repos_[appName])) {
88-
const repo = this.repos_[appName][dbUrl];
89-
if (repo) {
90-
repo.resume();
91-
}
85+
this.repos_[appName][dbUrl].resume();
9286
}
9387
}
9488
}
9589

90+
/**
91+
* Create a new repo based on an old one but pointing to a particular host and port.
92+
*/
93+
cloneRepoForEmulator(repo: Repo, host: string, port: number): Repo {
94+
const nodeAdmin = repo.repoInfo_.nodeAdmin;
95+
const url = `http://${host}:${port}?ns=${repo.repoInfo_.namespace}`;
96+
const authTokenProvider = nodeAdmin
97+
? new EmulatorAdminTokenProvider()
98+
: repo.authTokenProvider;
99+
100+
const parsedUrl = parseRepoInfo(url, nodeAdmin);
101+
102+
return this.createRepo(parsedUrl.repoInfo, repo.app, authTokenProvider);
103+
}
104+
96105
/**
97106
* This function should only ever be called to CREATE a new database instance.
98107
*
@@ -150,11 +159,9 @@ export class RepoManager {
150159
);
151160
}
152161

153-
return new Database(
154-
repoInfo,
155-
app,
156-
authTokenProvider
157-
);
162+
const repo = this.createRepo(repoInfo, app, authTokenProvider);
163+
164+
return repo.database;
158165
}
159166

160167
/**
@@ -185,64 +192,25 @@ export class RepoManager {
185192
createRepo(
186193
repoInfo: RepoInfo,
187194
app: FirebaseApp,
188-
authTokenProvider: AuthTokenProvider,
189-
database: Database,
195+
authTokenProvider: AuthTokenProvider
190196
): Repo {
191197
let appRepos = safeGet(this.repos_, app.name);
192-
if (!appRepos) {
193-
appRepos = {};
194-
this.repos_[app.name] = appRepos;
195-
}
196-
197-
this.assertUnique(repoInfo, app);
198-
const repo = new Repo(repoInfo, this.useRestClient_, app, authTokenProvider, database);
199-
appRepos[repoInfo.toURLString()] = repo;
200-
201-
return repo;
202-
}
203-
204-
/**
205-
* Reserve an info/app combination for future lazy repo creation.
206-
* @param repoInfo The metadata about the Repo.
207-
* @param app The FirebaseApp.
208-
*/
209-
reserveRepo(
210-
repoInfo: RepoInfo,
211-
app: FirebaseApp,
212-
) {
213-
this.assertUnique(repoInfo, app);
214198

215-
let appRepos = safeGet(this.repos_, app.name);
216199
if (!appRepos) {
217200
appRepos = {};
218201
this.repos_[app.name] = appRepos;
219202
}
220203

221-
// Reserve the spot by putting 'null' in the map.
222-
// We know we're not overwriting anything because of assertUnique
223-
appRepos[repoInfo.toURLString()] = null;
224-
}
225-
226-
/**
227-
* Make sure no matching Repo already exists.
228-
* @param repoInfo The metadata about the Repo.
229-
* @param app The FirebaseApp.
230-
*/
231-
assertUnique(
232-
repoInfo: RepoInfo,
233-
app: FirebaseApp,
234-
) {
235-
const appRepos = safeGet(this.repos_, app.name);
236-
if (!appRepos) {
237-
return;
238-
}
239-
240-
const repo = safeGet(appRepos, repoInfo.toURLString());
241-
if (repo !== undefined) {
204+
let repo = safeGet(appRepos, repoInfo.toURLString());
205+
if (repo) {
242206
fatal(
243207
'Database initialized multiple times. Please make sure the format of the database URL matches with each database() call.'
244208
);
245209
}
210+
repo = new Repo(repoInfo, this.useRestClient_, app, authTokenProvider);
211+
appRepos[repoInfo.toURLString()] = repo;
212+
213+
return repo;
246214
}
247215

248216
/**

0 commit comments

Comments
 (0)