Skip to content

Commit 59a7208

Browse files
Merging Master into Multi-Tab (#1045)
* Add @davideast as a CODEOWNER (#996) * Embed metadata directly into the RPC call (#979) * Embed metadata directly into the RPC call * [AUTOMATED]: Prettier Code Styling * Use ...args * [AUTOMATED]: Prettier Code Styling * Minimize diff * Add the OAuth assertion back in * Added missing type for optional database url. (#1001) * RxFire Realtime Database (#997) * initial database code * test setup * database tests * auditTrail and database tests * [AUTOMATED]: Prettier Code Styling * [AUTOMATED]: License Headers * Josh's comments. Database docs * [AUTOMATED]: Prettier Code Styling * Firestore docs * auth docs * declaration fixes * switch to peerDeps * [AUTOMATED]: Prettier Code Styling * test config * Expose array transforms and array contains queries. (#1004) Also remove test code that was combining multiple array contains queries since those were disallowed in 04c9c3a. * Move fieldFilter (free function) to Filter.create() (#988) This is a refactoring to unify filter creation across platforms. * Enable firestore sdk to talk to emulator (#1007) * Enable firestore sdk to talk to emulator * [AUTOMATED]: Prettier Code Styling * Revert firestore sdk changes * [AUTOMATED]: Prettier Code Styling * Revert credentials.ts * Cleanup * [AUTOMATED]: Prettier Code Styling * Set webSafe=false * Combine initializeTestApp and initializeFirestoreTestApp * [AUTOMATED]: Prettier Code Styling * Cleanup * [AUTOMATED]: Prettier Code Styling * Update major version since this is a breaking change that will cause the testing sdk to no longer work with old versions of the RTDB emulator * Completely remove admin sdk * Change version back to 0.1.0 * Setting GarbageSource in SyncEngine's constructor (#1010) * b/72533250: Fix issue with limbo resolutions triggering incorrect manufactured deletes. (#1014) This fixes an issue occurring when a limbo target receives a documentUpdate, then a global snapshot, and then a CURRENT. Because there was a global snapshot before the CURRENT, WatchChangeAggregator has no pending document updates and calls SyncEngine.targetContainsDocument() to see if we previously got any document from the backend for the target. See: https://github.com/firebase/firebase-js-sdk/blob/6905339235ad801291edc696dd75a08e80647f5b/packages/firestore/src/remote/watch_change.ts#L422 Prior to this change, targetContainsDocument() returned false because it relies on our Views to track the contents of the target, and we don't have Views for limbo targets. Thus WatchChangeAggregator incorrectly manufactures a NoDocument document update which deletes data from our cache. The fix is to have SyncEngine track the fact that we did indeed get a document for the limbo resolution and return true from targetContainsDocument(). * Updating yarn.lock * Add @firebase/util as a dep of @firebase/testing * Allow remote updates from watch to heal a cache with synthesized deletes in it (#1015) * Write a spec test for the busted cache * Modify spec test to demonstrate deletedDoc issue. (#1017) * Allow updates for targets where the document is modified * Fix getRemoteKeysForTarget() method name in comment. (#1020) While porting I noticed this was slightly wrong. targetContainsDocument() is the method in WatchChangeAggregator. The SyncEngine method I meant to reference is getRemoteKeysForTarget(). * Making sure we don't export 'experimental' (#1023) * Add a schema migration that drops the query cache (#1019) * Add a schema migration that drops the query cache This is a force fix for potential existence filter mismatches caused by firebase/firebase-ios-sdk#1548 The essential problem is that when resuming a query, the server is allowed to forget deletes. If the number of incorrectly synthesized deletes matches the number of server-forgotten deletes then the existence filter can give a false positive, preventing the cache from self healing. Dropping the query cache clears any client-side resume token which prevents a false positive existence filter mismatch. Note that the remote document cache and mutation queues are unaffected so any cached documents that do exist will still work while offline. * Implement review feedback * Add a release note for the fix to #1548 (#1024) * Ensure that we create an empty TargetGlobal row. (#1029) Ensure the v3 migration unconditionally creates the TargetGlobal row. Remove the no-longer-necessary v2 schema migration. * Remove unnecessary `any` (#1030) * Fix an errant any usage * [AUTOMATED]: Prettier Code Styling * Publish [email protected] * Unify local.QueryData with the other platforms (#1027) This makes it line up with it's own docs, and also the other platforms. * Fix to #1027 to allow SnapshotVersion == 0 (#1033) * Add iat to fake access token payload (#1022) * Add iat to fake access token payload * [AUTOMATED]: Prettier Code Styling * Simpler tests * [AUTOMATED]: Prettier Code Styling * Do not clobber iat * catch server error RESET_PASSWORD_EXCEED_LIMIT (#1037) * Merging Master into Multi-Tab (#1038)
1 parent 0a4c43b commit 59a7208

Some content is hidden

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

69 files changed

+2400
-1003
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ packages/auth-types @bojeil-google @wti806
2929

3030
# Testing Code
3131
packages/testing @tonymeng @ryanpbrewster
32+
33+
# RxFire Code
34+
packages/rxfire @davideast

integration/browserify/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"test": "karma start --single-run"
88
},
99
"dependencies": {
10-
"firebase": "5.2.0"
10+
"firebase": "5.3.0"
1111
},
1212
"devDependencies": {
1313
"@babel/core": "7.0.0-beta.47",

integration/firebase-typings/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"test": "tsc index.ts --outDir dist"
77
},
88
"dependencies": {
9-
"firebase": "5.2.0"
9+
"firebase": "5.3.0"
1010
},
1111
"devDependencies": {
1212
"typescript": "2.8.1"

integration/messaging/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"test:manual": "mocha --exit"
99
},
1010
"dependencies": {
11-
"firebase": "5.2.0"
11+
"firebase": "5.3.0"
1212
},
1313
"devDependencies": {
1414
"chai": "4.1.2",

integration/typescript/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"test": "karma start --single-run"
77
},
88
"dependencies": {
9-
"firebase": "5.2.0"
9+
"firebase": "5.3.0"
1010
},
1111
"devDependencies": {
1212
"@babel/core": "7.0.0-beta.47",

integration/webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"test": "karma start --single-run"
88
},
99
"dependencies": {
10-
"firebase": "5.2.0"
10+
"firebase": "5.3.0"
1111
},
1212
"devDependencies": {
1313
"@babel/core": "7.0.0-beta.47",

packages/auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@firebase/auth",
3-
"version": "0.7.0",
3+
"version": "0.7.1",
44
"main": "dist/auth.js",
55
"module": "dist/auth.esm.js",
66
"description": "Javascript library for Firebase Auth SDK",

packages/auth/src/rpchandler.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ fireauth.RpcHandler.ServerError = {
224224
OPERATION_NOT_ALLOWED: 'OPERATION_NOT_ALLOWED',
225225
PASSWORD_LOGIN_DISABLED: 'PASSWORD_LOGIN_DISABLED',
226226
QUOTA_EXCEEDED: 'QUOTA_EXCEEDED',
227+
RESET_PASSWORD_EXCEED_LIMIT: 'RESET_PASSWORD_EXCEED_LIMIT',
227228
SESSION_EXPIRED: 'SESSION_EXPIRED',
228229
TOKEN_EXPIRED: 'TOKEN_EXPIRED',
229230
TOO_MANY_ATTEMPTS_TRY_LATER: 'TOO_MANY_ATTEMPTS_TRY_LATER',
@@ -2231,6 +2232,8 @@ fireauth.RpcHandler.getDeveloperError_ =
22312232
// Send Password reset email errors:
22322233
errorMap[fireauth.RpcHandler.ServerError.EMAIL_NOT_FOUND] =
22332234
fireauth.authenum.Error.USER_DELETED;
2235+
errorMap[fireauth.RpcHandler.ServerError.RESET_PASSWORD_EXCEED_LIMIT] =
2236+
fireauth.authenum.Error.TOO_MANY_ATTEMPTS_TRY_LATER;
22342237

22352238
// Reset password errors:
22362239
errorMap[fireauth.RpcHandler.ServerError.EXPIRED_OOB_CODE] =

packages/auth/test/rpchandler_test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3994,6 +3994,8 @@ function testSendPasswordResetEmail_caughtServerError() {
39943994
var errorMap = {};
39953995
errorMap[fireauth.RpcHandler.ServerError.EMAIL_NOT_FOUND] =
39963996
fireauth.authenum.Error.USER_DELETED;
3997+
errorMap[fireauth.RpcHandler.ServerError.RESET_PASSWORD_EXCEED_LIMIT] =
3998+
fireauth.authenum.Error.TOO_MANY_ATTEMPTS_TRY_LATER;
39973999
errorMap[fireauth.RpcHandler.ServerError.INVALID_RECIPIENT_EMAIL] =
39984000
fireauth.authenum.Error.INVALID_RECIPIENT_EMAIL;
39994001
errorMap[fireauth.RpcHandler.ServerError.INVALID_SENDER] =

packages/firebase/index.d.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ declare namespace firebase {
125125
declare namespace firebase.app {
126126
interface App {
127127
auth(): firebase.auth.Auth;
128-
database(): firebase.database.Database;
128+
database(url?: string): firebase.database.Database;
129129
delete(): Promise<any>;
130130
messaging(): firebase.messaging.Messaging;
131131
name: string;
@@ -1603,10 +1603,9 @@ declare namespace firebase.firestore {
16031603

16041604
/**
16051605
* Filter conditions in a `Query.where()` clause are specified using the
1606-
* strings '<', '<=', '==', '>=', and '>'.
1606+
* strings '<', '<=', '==', '>=', '>', and 'array-contains'.
16071607
*/
1608-
// TODO(array-features): Add 'array-contains' once backend support lands.
1609-
export type WhereFilterOp = '<' | '<=' | '==' | '>=' | '>';
1608+
export type WhereFilterOp = '<' | '<=' | '==' | '>=' | '>' | 'array-contains';
16101609

16111610
/**
16121611
* A `Query` refers to a Query which you can read or listen to. You can also
@@ -1986,8 +1985,7 @@ declare namespace firebase.firestore {
19861985
* @param elements The elements to union into the array.
19871986
* @return The FieldValue sentinel for use in a call to set() or update().
19881987
*/
1989-
// TODO(array-features): Expose this once backend support lands.
1990-
//static arrayUnion(...elements: any[]): FieldValue;
1988+
static arrayUnion(...elements: any[]): FieldValue;
19911989

19921990
/**
19931991
* Returns a special value that can be used with set() or update() that tells
@@ -1999,8 +1997,7 @@ declare namespace firebase.firestore {
19991997
* @param elements The elements to remove from the array.
20001998
* @return The FieldValue sentinel for use in a call to set() or update().
20011999
*/
2002-
// TODO(array-features): Expose this once backend support lands.
2003-
//static arrayRemove(...elements: any[]): FieldValue;
2000+
static arrayRemove(...elements: any[]): FieldValue;
20042001

20052002
/**
20062003
* Returns true if this `FieldValue` is equal to the provided one.

packages/firebase/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "firebase",
3-
"version": "5.2.0",
3+
"version": "5.3.0",
44
"description": "Firebase JavaScript library for web and Node.js",
55
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
66
"license": "Apache-2.0",
@@ -36,9 +36,9 @@
3636
"react-native": "dist/index.rn.cjs.js",
3737
"dependencies": {
3838
"@firebase/app": "0.3.3",
39-
"@firebase/auth": "0.7.0",
39+
"@firebase/auth": "0.7.1",
4040
"@firebase/database": "0.3.4",
41-
"@firebase/firestore": "0.5.6",
41+
"@firebase/firestore": "0.6.0",
4242
"@firebase/functions": "0.3.0",
4343
"@firebase/messaging": "0.3.5",
4444
"@firebase/polyfill": "0.3.3",

packages/firestore-types/index.d.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -891,10 +891,9 @@ export type OrderByDirection = 'desc' | 'asc';
891891

892892
/**
893893
* Filter conditions in a `Query.where()` clause are specified using the
894-
* strings '<', '<=', '==', '>=', and '>'.
894+
* strings '<', '<=', '==', '>=', '>', and 'array-contains'.
895895
*/
896-
// TODO(array-features): Add 'array-contains' once backend support lands.
897-
export type WhereFilterOp = '<' | '<=' | '==' | '>=' | '>';
896+
export type WhereFilterOp = '<' | '<=' | '==' | '>=' | '>' | 'array-contains';
898897

899898
/**
900899
* A `Query` refers to a Query which you can read or listen to. You can also
@@ -1270,8 +1269,7 @@ export class FieldValue {
12701269
* @param elements The elements to union into the array.
12711270
* @return The FieldValue sentinel for use in a call to set() or update().
12721271
*/
1273-
// TODO(array-features): Expose this once backend support lands.
1274-
//static arrayUnion(...elements: any[]): FieldValue;
1272+
static arrayUnion(...elements: any[]): FieldValue;
12751273

12761274
/**
12771275
* Returns a special value that can be used with set() or update() that tells
@@ -1283,8 +1281,7 @@ export class FieldValue {
12831281
* @param elements The elements to remove from the array.
12841282
* @return The FieldValue sentinel for use in a call to set() or update().
12851283
*/
1286-
// TODO(array-features): Expose this once backend support lands.
1287-
//static arrayRemove(...elements: any[]): FieldValue;
1284+
static arrayRemove(...elements: any[]): FieldValue;
12881285

12891286
/**
12901287
* Returns true if this `FieldValue` is equal to the provided one.

packages/firestore-types/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@firebase/firestore-types",
3-
"version": "0.4.3",
3+
"version": "0.5.0",
44
"description": "@firebase/firestore Types",
55
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
66
"license": "Apache-2.0",

packages/firestore/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
# Unreleased
2+
- [fixed] Fixed an issue where documents could be cached as deleted when
3+
they should not have been, leading to queries returning fewer results than
4+
they should (firebase/firebase-ios-sdk#1548).
5+
- [feature] Added `firebase.firestore.FieldValue.arrayUnion()` and
6+
`firebase.firestore.FieldValue.arrayRemove()` to atomically add and remove
7+
elements from an array field in a document.
8+
- [feature] Added `'array-contains'` query operator for use with `.where()` to
9+
find documents where an array field contains a specific element.
210

311
# 0.5.0
412
- [changed] Merged the `includeQueryMetadataChanges` and

packages/firestore/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@firebase/firestore",
3-
"version": "0.5.6",
3+
"version": "0.6.0",
44
"description": "",
55
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
66
"scripts": {
@@ -25,7 +25,7 @@
2525
"dist"
2626
],
2727
"dependencies": {
28-
"@firebase/firestore-types": "0.4.3",
28+
"@firebase/firestore-types": "0.5.0",
2929
"@firebase/logger": "0.1.1",
3030
"@firebase/webchannel-wrapper": "0.2.8",
3131
"grpc": "1.11.3",

packages/firestore/src/api/database.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import { FirestoreClient } from '../core/firestore_client';
2525
import {
2626
Bound,
2727
Direction,
28-
fieldFilter,
2928
Filter,
3029
OrderBy,
3130
Query as InternalQuery,
@@ -1374,7 +1373,7 @@ export class Query implements firestore.Query {
13741373
value
13751374
);
13761375
}
1377-
const filter = fieldFilter(fieldPath, relationOp, fieldValue);
1376+
const filter = Filter.create(fieldPath, relationOp, fieldValue);
13781377
this.validateNewFilter(filter);
13791378
return new Query(this._query.addFilter(filter), this.firestore);
13801379
}

packages/firestore/src/api/field_value.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,14 @@ export abstract class FieldValueImpl implements firestore.FieldValue {
3636
return ServerTimestampFieldValueImpl.instance;
3737
}
3838

39-
// TODO(array-features): Expose this once backend support lands.
40-
static _arrayUnion(...elements: AnyJs[]): FieldValueImpl {
39+
static arrayUnion(...elements: AnyJs[]): FieldValueImpl {
4140
validateAtLeastNumberOfArgs('FieldValue.arrayUnion', arguments, 1);
4241
// NOTE: We don't actually parse the data until it's used in set() or
4342
// update() since we need access to the Firestore instance.
4443
return new ArrayUnionFieldValueImpl(elements);
4544
}
4645

47-
// TODO(array-features): Expose this once backend support lands.
48-
static _arrayRemove(...elements: AnyJs[]): FieldValueImpl {
46+
static arrayRemove(...elements: AnyJs[]): FieldValueImpl {
4947
validateAtLeastNumberOfArgs('FieldValue.arrayRemove', arguments, 1);
5048
// NOTE: We don't actually parse the data until it's used in set() or
5149
// update() since we need access to the Firestore instance.

packages/firestore/src/core/query.ts

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,35 @@ export class Query {
390390
}
391391
}
392392

393-
export interface Filter {
394-
matches(doc: Document): boolean;
395-
canonicalId(): string;
396-
isEqual(filter: Filter): boolean;
393+
export abstract class Filter {
394+
abstract matches(doc: Document): boolean;
395+
abstract canonicalId(): string;
396+
abstract isEqual(filter: Filter): boolean;
397+
398+
/**
399+
* Creates a filter based on the provided arguments.
400+
*/
401+
static create(field: FieldPath, op: RelationOp, value: FieldValue): Filter {
402+
if (value.isEqual(NullValue.INSTANCE)) {
403+
if (op !== RelationOp.EQUAL) {
404+
throw new FirestoreError(
405+
Code.INVALID_ARGUMENT,
406+
'Invalid query. You can only perform equals comparisons on null.'
407+
);
408+
}
409+
return new NullFilter(field);
410+
} else if (value.isEqual(DoubleValue.NAN)) {
411+
if (op !== RelationOp.EQUAL) {
412+
throw new FirestoreError(
413+
Code.INVALID_ARGUMENT,
414+
'Invalid query. You can only perform equals comparisons on NaN.'
415+
);
416+
}
417+
return new NanFilter(field);
418+
} else {
419+
return new RelationFilter(field, op, value);
420+
}
421+
}
397422
}
398423

399424
export class RelationOp {
@@ -434,12 +459,14 @@ export class RelationOp {
434459
}
435460
}
436461

437-
export class RelationFilter implements Filter {
462+
export class RelationFilter extends Filter {
438463
constructor(
439464
public field: FieldPath,
440465
public op: RelationOp,
441466
public value: FieldValue
442-
) {}
467+
) {
468+
super();
469+
}
443470

444471
matches(doc: Document): boolean {
445472
if (this.field.isKeyField()) {
@@ -528,8 +555,10 @@ export class RelationFilter implements Filter {
528555
/**
529556
* Filter that matches 'null' values.
530557
*/
531-
export class NullFilter implements Filter {
532-
constructor(public field: FieldPath) {}
558+
export class NullFilter extends Filter {
559+
constructor(public field: FieldPath) {
560+
super();
561+
}
533562

534563
matches(doc: Document): boolean {
535564
const val = doc.field(this.field);
@@ -556,8 +585,10 @@ export class NullFilter implements Filter {
556585
/**
557586
* Filter that matches 'NaN' values.
558587
*/
559-
export class NanFilter implements Filter {
560-
constructor(public field: FieldPath) {}
588+
export class NanFilter extends Filter {
589+
constructor(public field: FieldPath) {
590+
super();
591+
}
561592

562593
matches(doc: Document): boolean {
563594
const val = doc.field(this.field).value();
@@ -581,35 +612,6 @@ export class NanFilter implements Filter {
581612
}
582613
}
583614

584-
/**
585-
* Creates a filter based on the provided arguments.
586-
*/
587-
export function fieldFilter(
588-
field: FieldPath,
589-
op: RelationOp,
590-
value: FieldValue
591-
): Filter {
592-
if (value.isEqual(NullValue.INSTANCE)) {
593-
if (op !== RelationOp.EQUAL) {
594-
throw new FirestoreError(
595-
Code.INVALID_ARGUMENT,
596-
'Invalid query. You can only perform equals ' + 'comparisons on null.'
597-
);
598-
}
599-
return new NullFilter(field);
600-
} else if (value.isEqual(DoubleValue.NAN)) {
601-
if (op !== RelationOp.EQUAL) {
602-
throw new FirestoreError(
603-
Code.INVALID_ARGUMENT,
604-
'Invalid query. You can only perform equals ' + 'comparisons on NaN.'
605-
);
606-
}
607-
return new NanFilter(field);
608-
} else {
609-
return new RelationFilter(field, op, value);
610-
}
611-
}
612-
613615
/**
614616
* The direction of sorting in an order by.
615617
*/

0 commit comments

Comments
 (0)