Skip to content

Commit 6dffdf2

Browse files
authored
Merge firestore bundles implementation without exposing public APIs (#3594)
1 parent eff049b commit 6dffdf2

File tree

71 files changed

+4562
-255
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+4562
-255
lines changed

.changeset/lemon-steaks-draw.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/firestore": internal
3+
---
4+
5+
Merge bundle loading implementation without exposing public API

packages-exp/auth-exp/index.webworker.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ registerAuth(ClientPlatform.WORKER);
3737
export function getAuth(app = getApp()): Auth {
3838
// Unlike the other environments, we need to explicitly check if indexedDb is
3939
// available. That means doing the whole rigamarole
40-
const auth = _getProvider(app, _ComponentName.AUTH).getImmediate() as AuthImpl;
40+
const auth = _getProvider(
41+
app,
42+
_ComponentName.AUTH
43+
).getImmediate() as AuthImpl;
4144

4245
// This promise is intended to float; auth initialization happens in the
4346
// background, meanwhile the auth object may be used by the app.

packages/database/src/api/Database.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,17 @@ export class Database implements FirebaseService {
157157
validateUrl(apiName, 1, parsedURL);
158158

159159
const repoInfo = parsedURL.repoInfo;
160-
if (!repoInfo.isCustomHost() && repoInfo.host !== this.repo_.repoInfo_.host) {
160+
if (
161+
!repoInfo.isCustomHost() &&
162+
repoInfo.host !== this.repo_.repoInfo_.host
163+
) {
161164
fatal(
162165
apiName +
163166
': Host name does not match the current database: ' +
164167
'(found ' +
165168
repoInfo.host +
166169
' but expected ' +
167-
this.repo_.repoInfo_.host+
170+
this.repo_.repoInfo_.host +
168171
')'
169172
);
170173
}

packages/firestore/exp/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ export {
3131
waitForPendingWrites,
3232
disableNetwork,
3333
enableNetwork,
34-
terminate,
35-
Settings
34+
terminate
3635
} from './src/api/database';
3736

3837
export {

packages/firestore/externs.json

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"packages/webchannel-wrapper/src/index.d.ts",
2929
"packages/util/dist/src/crypt.d.ts",
3030
"packages/util/dist/src/environment.d.ts",
31+
"packages/firestore/src/protos/firestore_bundle_proto.ts",
3132
"packages/firestore/src/protos/firestore_proto_api.d.ts",
3233
"packages/firestore/src/util/error.ts",
3334
"packages/firestore/src/local/indexeddb_schema.ts",

packages/firestore/rollup.shared.js

+69-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,75 @@ const manglePrivatePropertiesOptions = {
129129
},
130130
mangle: {
131131
properties: {
132-
regex: /^__PRIVATE_/
132+
regex: /^__PRIVATE_/,
133+
// All JS Keywords are reserved. Although this should be taken cared of by
134+
// Terser, we have seen issues with `do`, hence the extra caution.
135+
reserved: [
136+
'abstract',
137+
'arguments',
138+
'await',
139+
'boolean',
140+
'break',
141+
'byte',
142+
'case',
143+
'catch',
144+
'char',
145+
'class',
146+
'const',
147+
'continue',
148+
'debugger',
149+
'default',
150+
'delete',
151+
'do',
152+
'double',
153+
'else',
154+
'enum',
155+
'eval',
156+
'export',
157+
'extends',
158+
'false',
159+
'final',
160+
'finally',
161+
'float',
162+
'for',
163+
'function',
164+
'goto',
165+
'if',
166+
'implements',
167+
'import',
168+
'in',
169+
'instanceof',
170+
'int',
171+
'interface',
172+
'let',
173+
'long',
174+
'native',
175+
'new',
176+
'null',
177+
'package',
178+
'private',
179+
'protected',
180+
'public',
181+
'return',
182+
'short',
183+
'static',
184+
'super',
185+
'switch',
186+
'synchronized',
187+
'this',
188+
'throw',
189+
'throws',
190+
'transient',
191+
'true',
192+
'try',
193+
'typeof',
194+
'var',
195+
'void',
196+
'volatile',
197+
'while',
198+
'with',
199+
'yield'
200+
]
133201
}
134202
}
135203
};

packages/firestore/src/api/bundle.ts

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { Deferred } from '../util/promise';
19+
import { PartialObserver } from './observer';
20+
import { debugAssert } from '../util/assert';
21+
import { FirestoreError } from '../util/error';
22+
23+
export interface ApiLoadBundleTask {
24+
onProgress(
25+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
26+
next?: (progress: ApiLoadBundleTaskProgress) => any,
27+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
28+
error?: (error: Error) => any,
29+
complete?: () => void
30+
): void;
31+
32+
then<T, R>(
33+
onFulfilled?: (a: ApiLoadBundleTaskProgress) => T | PromiseLike<T>,
34+
onRejected?: (a: Error) => R | PromiseLike<R>
35+
): Promise<T | R>;
36+
37+
catch<R>(
38+
onRejected: (a: Error) => R | PromiseLike<R>
39+
): Promise<R | ApiLoadBundleTaskProgress>;
40+
}
41+
42+
export interface ApiLoadBundleTaskProgress {
43+
documentsLoaded: number;
44+
totalDocuments: number;
45+
bytesLoaded: number;
46+
totalBytes: number;
47+
taskState: TaskState;
48+
}
49+
50+
export type TaskState = 'Error' | 'Running' | 'Success';
51+
52+
export class LoadBundleTask
53+
implements ApiLoadBundleTask, PromiseLike<ApiLoadBundleTaskProgress> {
54+
private _progressObserver: PartialObserver<ApiLoadBundleTaskProgress> = {};
55+
private _taskCompletionResolver = new Deferred<ApiLoadBundleTaskProgress>();
56+
57+
private _lastProgress: ApiLoadBundleTaskProgress = {
58+
taskState: 'Running',
59+
totalBytes: 0,
60+
totalDocuments: 0,
61+
bytesLoaded: 0,
62+
documentsLoaded: 0
63+
};
64+
65+
onProgress(
66+
next?: (progress: ApiLoadBundleTaskProgress) => unknown,
67+
error?: (err: Error) => unknown,
68+
complete?: () => void
69+
): void {
70+
this._progressObserver = {
71+
next,
72+
error,
73+
complete
74+
};
75+
}
76+
77+
catch<R>(
78+
onRejected: (a: Error) => R | PromiseLike<R>
79+
): Promise<R | ApiLoadBundleTaskProgress> {
80+
return this._taskCompletionResolver.promise.catch(onRejected);
81+
}
82+
83+
then<T, R>(
84+
onFulfilled?: (a: ApiLoadBundleTaskProgress) => T | PromiseLike<T>,
85+
onRejected?: (a: Error) => R | PromiseLike<R>
86+
): Promise<T | R> {
87+
return this._taskCompletionResolver.promise.then(onFulfilled, onRejected);
88+
}
89+
90+
/**
91+
* Notifies all observers that bundle loading has completed, with a provided
92+
* `LoadBundleTaskProgress` object.
93+
*/
94+
_completeWith(progress: ApiLoadBundleTaskProgress): void {
95+
debugAssert(
96+
progress.taskState === 'Success',
97+
'Task is not completed with Success.'
98+
);
99+
this._updateProgress(progress);
100+
if (this._progressObserver.complete) {
101+
this._progressObserver.complete();
102+
}
103+
104+
this._taskCompletionResolver.resolve(progress);
105+
}
106+
107+
/**
108+
* Notifies all observers that bundle loading has failed, with a provided
109+
* `Error` as the reason.
110+
*/
111+
_failWith(error: FirestoreError): void {
112+
this._lastProgress.taskState = 'Error';
113+
114+
if (this._progressObserver.next) {
115+
this._progressObserver.next(this._lastProgress);
116+
}
117+
118+
if (this._progressObserver.error) {
119+
this._progressObserver.error(error);
120+
}
121+
122+
this._taskCompletionResolver.reject(error);
123+
}
124+
125+
/**
126+
* Notifies a progress update of loading a bundle.
127+
* @param progress The new progress.
128+
*/
129+
_updateProgress(progress: ApiLoadBundleTaskProgress): void {
130+
debugAssert(
131+
this._lastProgress.taskState === 'Running',
132+
'Cannot update progress on a completed or failed task'
133+
);
134+
135+
this._lastProgress = progress;
136+
if (this._progressObserver.next) {
137+
this._progressObserver.next(progress);
138+
}
139+
}
140+
}

packages/firestore/src/api/database.ts

+33
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import {
2525
FirestoreClient,
2626
firestoreClientGetDocumentsFromLocalCache,
2727
firestoreClientGetDocumentsViaSnapshotListener,
28+
firestoreClientGetNamedQuery,
2829
firestoreClientListen,
30+
firestoreClientLoadBundle,
2931
firestoreClientTransaction,
3032
firestoreClientWrite
3133
} from '../core/firestore_client';
@@ -157,6 +159,7 @@ import {
157159

158160
import { makeDatabaseInfo } from '../../lite/src/api/database';
159161
import { DEFAULT_HOST } from '../../lite/src/api/components';
162+
import { ApiLoadBundleTask, LoadBundleTask } from './bundle';
160163

161164
/**
162165
* Constant used to indicate the LRU garbage collection should be disabled.
@@ -440,6 +443,36 @@ export function setLogLevel(level: PublicLogLevel): void {
440443
setClientLogLevel(level);
441444
}
442445

446+
export function loadBundle(
447+
db: Firestore,
448+
bundleData: ArrayBuffer | ReadableStream<Uint8Array> | string
449+
): ApiLoadBundleTask {
450+
const resultTask = new LoadBundleTask();
451+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
452+
firestoreClientLoadBundle(
453+
ensureFirestoreConfigured(db._delegate),
454+
bundleData,
455+
resultTask
456+
);
457+
return resultTask;
458+
}
459+
460+
export function namedQuery(
461+
db: Firestore,
462+
name: string
463+
): Promise<PublicQuery | null> {
464+
return firestoreClientGetNamedQuery(
465+
ensureFirestoreConfigured(db._delegate),
466+
name
467+
).then(namedQuery => {
468+
if (!namedQuery) {
469+
return null;
470+
}
471+
472+
return new Query(namedQuery.query, db, null);
473+
});
474+
}
475+
443476
/**
444477
* A reference to a transaction.
445478
*/

0 commit comments

Comments
 (0)