Skip to content

Commit c38f0fa

Browse files
Review
1 parent 3c8b6f5 commit c38f0fa

File tree

13 files changed

+70
-99
lines changed

13 files changed

+70
-99
lines changed

config/webpack.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ module.exports = {
8686
new webpack.NormalModuleReplacementPlugin(
8787
FIRESTORE_PLATFORM_RE,
8888
resource => {
89+
const targetPlatform = process.env.TEST_PLATFORM || 'browser';
8990
resource.request = resource.request.replace(
9091
FIRESTORE_PLATFORM_RE,
91-
'$1/platform/browser/$2.ts'
92+
`$1/platform/${targetPlatform}/$2.ts`
9293
);
9394
}
9495
),

packages/firestore/exp/test/bootstrap.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import '../register';
2424
* https://github.com/webpack-contrib/karma-webpack#alternative-usage
2525
*/
2626

27-
process.env.TEST_PLATFORM = 'browser';
28-
2927
// 'context()' definition requires additional dependency on webpack-env package.
3028
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3129
const testsContext = (require as any).context(

packages/firestore/karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function getTestFiles(argv) {
5555
} else if (argv.integration) {
5656
return [legcayIntegrationTests];
5757
} else if (argv.lite) {
58+
process.env.TEST_PLATFORM = 'browser_lite';
5859
return [liteIntegrationTests];
5960
} else if (argv.exp) {
6061
return [expIntegrationTests];

packages/firestore/lite/test/bootstrap.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import '../register';
2424
* https://github.com/webpack-contrib/karma-webpack#alternative-usage
2525
*/
2626

27-
process.env.TEST_PLATFORM = 'browser-lite';
28-
2927
// 'context()' definition requires additional dependency on webpack-env package.
3028
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3129
const testsContext = (require as any).context('.', true, /^.*\.test.*$/);

packages/firestore/src/platform/browser_lite/connection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ export { newConnectivityMonitor } from '../browser/connection';
2323

2424
/** Initializes the HTTP connection for the REST API. */
2525
export function newConnection(databaseInfo: DatabaseInfo): Promise<Connection> {
26-
return Promise.resolve(new FetchConnection(databaseInfo, fetch));
26+
return Promise.resolve(new FetchConnection(databaseInfo, fetch.bind(null)));
2727
}

packages/firestore/src/platform/node/grpc_connection.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ const LOG_TAG = 'Connection';
4646
// should use the Firebase version instead.
4747
const X_GOOG_API_CLIENT_VALUE = `gl-node/${process.versions.node} fire/${SDK_VERSION} grpc/${grpcVersion}`;
4848

49-
function createMetadata(
50-
databaseInfo: DatabaseInfo,
51-
token: Token | null
52-
): Metadata {
49+
function createMetadata(databasePath: string, token: Token | null): Metadata {
5350
hardAssert(
5451
token === null || token.type === 'OAuth',
5552
'If provided, token must be OAuth'
@@ -66,11 +63,7 @@ function createMetadata(
6663
metadata.set('x-goog-api-client', X_GOOG_API_CLIENT_VALUE);
6764
// This header is used to improve routing and project isolation by the
6865
// backend.
69-
metadata.set(
70-
'google-cloud-resource-prefix',
71-
`projects/${databaseInfo.databaseId.projectId}/` +
72-
`databases/${databaseInfo.databaseId.database}`
73-
);
66+
metadata.set('google-cloud-resource-prefix', databasePath);
7467
return metadata;
7568
}
7669

@@ -83,15 +76,17 @@ type GeneratedGrpcStub = any;
8376
* A Connection implemented by GRPC-Node.
8477
*/
8578
export class GrpcConnection implements Connection {
79+
private readonly databasePath: string;
8680
// eslint-disable-next-line @typescript-eslint/no-explicit-any
87-
private firestore: any;
81+
private readonly firestore: any;
8882

8983
// We cache stubs for the most-recently-used token.
9084
private cachedStub: GeneratedGrpcStub | null = null;
9185

9286
constructor(protos: GrpcObject, private databaseInfo: DatabaseInfo) {
9387
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9488
this.firestore = (protos as any)['google']['firestore']['v1'];
89+
this.databasePath = `projects/${databaseInfo.databaseId.projectId}/databases/${databaseInfo.databaseId.database}`;
9590
}
9691

9792
private ensureActiveStub(): GeneratedGrpcStub {
@@ -110,16 +105,18 @@ export class GrpcConnection implements Connection {
110105

111106
invokeRPC<Req, Resp>(
112107
rpcName: string,
108+
path: string,
113109
request: Req,
114110
token: Token | null
115111
): Promise<Resp> {
116112
const stub = this.ensureActiveStub();
117-
const metadata = createMetadata(this.databaseInfo, token);
113+
const metadata = createMetadata(this.databasePath, token);
114+
const jsonRequest = { database: this.databasePath, ...request };
118115

119116
return nodePromise((callback: NodeCallback<Resp>) => {
120117
logDebug(LOG_TAG, `RPC '${rpcName}' invoked with request:`, request);
121118
return stub[rpcName](
122-
request,
119+
jsonRequest,
123120
metadata,
124121
(grpcError?: ServiceError, value?: Resp) => {
125122
if (grpcError) {
@@ -145,6 +142,7 @@ export class GrpcConnection implements Connection {
145142

146143
invokeStreamingRPC<Req, Resp>(
147144
rpcName: string,
145+
path: string,
148146
request: Req,
149147
token: Token | null
150148
): Promise<Resp[]> {
@@ -157,8 +155,9 @@ export class GrpcConnection implements Connection {
157155
request
158156
);
159157
const stub = this.ensureActiveStub();
160-
const metadata = createMetadata(this.databaseInfo, token);
161-
const stream = stub[rpcName](request, metadata);
158+
const metadata = createMetadata(this.databasePath, token);
159+
const jsonRequest = { ...request, database: this.databasePath };
160+
const stream = stub[rpcName](jsonRequest, metadata);
162161
stream.on('data', (response: Resp) => {
163162
logDebug(LOG_TAG, `RPC ${rpcName} received result:`, response);
164163
results.push(response);
@@ -182,7 +181,7 @@ export class GrpcConnection implements Connection {
182181
token: Token | null
183182
): Stream<Req, Resp> {
184183
const stub = this.ensureActiveStub();
185-
const metadata = createMetadata(this.databaseInfo, token);
184+
const metadata = createMetadata(this.databasePath, token);
186185
const grpcStream = stub[rpcName](metadata);
187186

188187
let closed = false;

packages/firestore/src/remote/connection.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ export interface Connection {
3838
* representing the JSON to send.
3939
*
4040
* @param rpcName the name of the RPC to invoke
41+
* @param path the path to invoke this RPC on
4142
* @param request the Raw JSON object encoding of the request message
4243
* @param token the Token to use for the RPC.
4344
* @return a Promise containing the JSON object encoding of the response
4445
*/
4546
invokeRPC<Req, Resp>(
4647
rpcName: string,
48+
path: string,
4749
request: Req,
4850
token: Token | null
4951
): Promise<Resp>;
@@ -54,13 +56,15 @@ export interface Connection {
5456
* completion and then returned as an array.
5557
*
5658
* @param rpcName the name of the RPC to invoke
59+
* @param path the path to invoke this RPC on
5760
* @param request the Raw JSON object encoding of the request message
5861
* @param token the Token to use for the RPC.
5962
* @return a Promise containing an array with the JSON object encodings of the
6063
* responses
6164
*/
6265
invokeStreamingRPC<Req, Resp>(
6366
rpcName: string,
67+
path: string,
6468
request: Req,
6569
token: Token | null
6670
): Promise<Resp[]>;

packages/firestore/src/remote/datastore.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,21 @@ class DatastoreImpl extends Datastore {
8282
}
8383

8484
/** Gets an auth token and invokes the provided RPC. */
85-
invokeRPC<Req, Resp>(rpcName: string, request: Req): Promise<Resp> {
85+
invokeRPC<Req, Resp>(
86+
rpcName: string,
87+
path: string,
88+
request: Req
89+
): Promise<Resp> {
8690
this.verifyInitialized();
8791
return this.credentials
8892
.getToken()
8993
.then(token => {
90-
return this.connection.invokeRPC<Req, Resp>(rpcName, request, token);
94+
return this.connection.invokeRPC<Req, Resp>(
95+
rpcName,
96+
path,
97+
request,
98+
token
99+
);
91100
})
92101
.catch((error: FirestoreError) => {
93102
if (error.code === Code.UNAUTHENTICATED) {
@@ -100,6 +109,7 @@ class DatastoreImpl extends Datastore {
100109
/** Gets an auth token and invokes the provided RPC with streamed results. */
101110
invokeStreamingRPC<Req, Resp>(
102111
rpcName: string,
112+
path: string,
103113
request: Req
104114
): Promise<Resp[]> {
105115
this.verifyInitialized();
@@ -108,6 +118,7 @@ class DatastoreImpl extends Datastore {
108118
.then(token => {
109119
return this.connection.invokeStreamingRPC<Req, Resp>(
110120
rpcName,
121+
path,
111122
request,
112123
token
113124
);
@@ -139,26 +150,26 @@ export async function invokeCommitRpc(
139150
mutations: Mutation[]
140151
): Promise<void> {
141152
const datastoreImpl = debugCast(datastore, DatastoreImpl);
142-
const params = {
143-
database: getEncodedDatabaseId(datastoreImpl.serializer),
153+
const path = getEncodedDatabaseId(datastoreImpl.serializer) + '/documents';
154+
const request = {
144155
writes: mutations.map(m => toMutation(datastoreImpl.serializer, m))
145156
};
146-
await datastoreImpl.invokeRPC('Commit', params);
157+
await datastoreImpl.invokeRPC('Commit', path, request);
147158
}
148159

149160
export async function invokeBatchGetDocumentsRpc(
150161
datastore: Datastore,
151162
keys: DocumentKey[]
152163
): Promise<MaybeDocument[]> {
153164
const datastoreImpl = debugCast(datastore, DatastoreImpl);
154-
const params = {
155-
database: getEncodedDatabaseId(datastoreImpl.serializer),
165+
const path = getEncodedDatabaseId(datastoreImpl.serializer) + '/documents';
166+
const request = {
156167
documents: keys.map(k => toName(datastoreImpl.serializer, k))
157168
};
158169
const response = await datastoreImpl.invokeStreamingRPC<
159170
api.BatchGetDocumentsRequest,
160171
api.BatchGetDocumentsResponse
161-
>('BatchGetDocuments', params);
172+
>('BatchGetDocuments', path, request);
162173

163174
const docs = new Map<string, MaybeDocument>();
164175
response.forEach(proto => {
@@ -179,21 +190,11 @@ export async function invokeRunQueryRpc(
179190
query: Query
180191
): Promise<Document[]> {
181192
const datastoreImpl = debugCast(datastore, DatastoreImpl);
182-
const { structuredQuery, parent } = toQueryTarget(
183-
datastoreImpl.serializer,
184-
queryToTarget(query)
185-
);
186-
const params = {
187-
database: getEncodedDatabaseId(datastoreImpl.serializer),
188-
parent,
189-
structuredQuery
190-
};
191-
193+
const request = toQueryTarget(datastoreImpl.serializer, queryToTarget(query));
192194
const response = await datastoreImpl.invokeStreamingRPC<
193195
api.RunQueryRequest,
194196
api.RunQueryResponse
195-
>('RunQuery', params);
196-
197+
>('RunQuery', request.parent!, { structuredQuery: request.structuredQuery });
197198
return (
198199
response
199200
// Omit RunQueryResponses that only contain readTimes.

packages/firestore/src/remote/rest_connection.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { logDebug, logWarn } from '../util/log';
2323
import { FirestoreError } from '../util/error';
2424
import { StringMap } from '../util/types';
2525
import { debugAssert } from '../util/assert';
26-
import { Indexable } from '../util/misc';
2726

2827
const LOG_TAG = 'RestConnection';
2928

@@ -64,29 +63,17 @@ export abstract class RestConnection implements Connection {
6463

6564
invokeRPC<Req, Resp>(
6665
rpcName: string,
66+
path: string,
6767
req: Req,
6868
token: Token | null
6969
): Promise<Resp> {
70-
const url = this.makeUrl(rpcName, req);
71-
72-
// The database and/or parent field is already encoded in URL. Specifying it
73-
// again in the body is not necessary in production, and will cause
74-
// duplicate field errors in the Firestore Emulator. Let's remove it.
75-
const jsonObj = ({ ...req } as unknown) as Indexable;
76-
delete jsonObj.parent;
77-
delete jsonObj.database;
78-
79-
logDebug(LOG_TAG, 'Sending: ', url, jsonObj);
70+
const url = this.makeUrl(rpcName, path);
71+
logDebug(LOG_TAG, 'Sending: ', url, req);
8072

8173
const headers = {};
8274
this.modifyHeadersForRequest(headers, token);
8375

84-
return this.performRPCRequest<Indexable, Resp>(
85-
rpcName,
86-
url,
87-
headers,
88-
jsonObj
89-
).then(
76+
return this.performRPCRequest<Req, Resp>(rpcName, url, headers, req).then(
9077
response => {
9178
logDebug(LOG_TAG, 'Received: ', response);
9279
return response;
@@ -95,7 +82,7 @@ export abstract class RestConnection implements Connection {
9582
logWarn(
9683
LOG_TAG,
9784
`${rpcName} failed with error: `,
98-
err.message,
85+
err,
9986
'url: ',
10087
url,
10188
'request:',
@@ -108,12 +95,13 @@ export abstract class RestConnection implements Connection {
10895

10996
invokeStreamingRPC<Req, Resp>(
11097
rpcName: string,
98+
path: string,
11199
request: Req,
112100
token: Token | null
113101
): Promise<Resp[]> {
114102
// The REST API automatically aggregates all of the streamed results, so we
115103
// can just use the normal invoke() method.
116-
return this.invokeRPC<Req, Resp[]>(rpcName, request, token);
104+
return this.invokeRPC<Req, Resp[]>(rpcName, path, request, token);
117105
}
118106

119107
abstract openStream<Req, Resp>(
@@ -156,13 +144,12 @@ export abstract class RestConnection implements Connection {
156144
body: Req
157145
): Promise<Resp>;
158146

159-
private makeUrl<Req>(rpcName: string, req: Req): string {
147+
private makeUrl<Req>(rpcName: string, path: string): string {
160148
const urlRpcName = RPC_NAME_URL_MAPPING[rpcName];
161149
debugAssert(
162150
urlRpcName !== undefined,
163151
'Unknown REST mapping for: ' + rpcName
164152
);
165-
const path = ((req as unknown) as Indexable).parent || this.databaseRoot;
166153
return `${this.baseUrl}/${RPC_URL_VERSION}/${path}:${urlRpcName}`;
167154
}
168155
}

packages/firestore/test/integration/api/database.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import * as chaiAsPromised from 'chai-as-promised';
2020
import * as firestore from '@firebase/firestore-types';
2121
import { expect, use } from 'chai';
2222

23-
import { Deferred } from '../../util/promise';
23+
import { Deferred } from '@firebase/util';
2424
import { EventsAccumulator } from '../util/events_accumulator';
2525
import * as firebaseExport from '../util/firebase_export';
2626
import {

packages/firestore/test/integration/bootstrap.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import '../../index';
2424
* https://github.com/webpack-contrib/karma-webpack#alternative-usage
2525
*/
2626

27-
process.env.TEST_PLATFORM = 'browser';
28-
2927
// 'context()' definition requires additional dependency on webpack-env package.
3028
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3129
const testsContext = (require as any).context(

packages/firestore/test/unit/bootstrap.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
* https://github.com/webpack-contrib/karma-webpack#alternative-usage
2323
*/
2424

25-
process.env.TEST_PLATFORM = 'browser';
26-
2725
// 'context()' definition requires additional dependency on webpack-env package.
2826
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2927
const testsContext = (require as any).context(

0 commit comments

Comments
 (0)