Skip to content

Commit 2b4898c

Browse files
FieldPath Compat class
1 parent 14d023d commit 2b4898c

File tree

6 files changed

+111
-134
lines changed

6 files changed

+111
-134
lines changed

packages/firestore/lite/src/api/field_path.ts

+19-9
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { _BaseFieldPath } from '../../../src/api/field_path';
19-
import { DOCUMENT_KEY_NAME } from '../../../src/model/path';
18+
import {
19+
DOCUMENT_KEY_NAME,
20+
FieldPath as InternalFieldPath
21+
} from '../../../src/model/path';
22+
import { Code, FirestoreError } from '../../../src/util/error';
2023

2124
/**
2225
* A `FieldPath` refers to a field in a document. The path may consist of a
@@ -26,12 +29,9 @@ import { DOCUMENT_KEY_NAME } from '../../../src/model/path';
2629
* Create a `FieldPath` by providing field names. If more than one field
2730
* name is provided, the path will point to a nested field in a document.
2831
*/
29-
export class FieldPath extends _BaseFieldPath {
30-
// Note: This class is stripped down a copy of the FieldPath class in the
31-
// legacy SDK. The changes are:
32-
// - The `documentId()` static method has been removed
33-
// - Input validation is limited to errors that cannot be caught by the
34-
// TypeScript transpiler.
32+
export class FieldPath {
33+
/** Internal representation of a Firestore field path. */
34+
readonly _internalPath: InternalFieldPath;
3535

3636
/**
3737
* Creates a FieldPath from the provided field names. If more than one field
@@ -40,7 +40,17 @@ export class FieldPath extends _BaseFieldPath {
4040
* @param fieldNames A list of field names.
4141
*/
4242
constructor(...fieldNames: string[]) {
43-
super(fieldNames);
43+
for (let i = 0; i < fieldNames.length; ++i) {
44+
if (fieldNames[i].length === 0) {
45+
throw new FirestoreError(
46+
Code.INVALID_ARGUMENT,
47+
`Invalid field name at argument $(i + 1). ` +
48+
'Field names must not be empty.'
49+
);
50+
}
51+
}
52+
53+
this._internalPath = new InternalFieldPath(fieldNames);
4454
}
4555

4656
/**

packages/firestore/src/api/database.ts

+27-15
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ import {
7777
} from '../util/input_validation';
7878
import { logWarn, setLogLevel as setClientLogLevel } from '../util/log';
7979
import { AutoId } from '../util/misc';
80-
import { _BaseFieldPath, FieldPath as ExternalFieldPath } from './field_path';
80+
import { FieldPath as ExpFieldPath } from '../../lite/src/api/field_path';
8181
import {
8282
CompleteFn,
8383
ErrorFn,
@@ -119,6 +119,7 @@ import {
119119
DocumentData as PublicDocumentData,
120120
DocumentReference as PublicDocumentReference,
121121
DocumentSnapshot as PublicDocumentSnapshot,
122+
FieldPath as PublicFieldPath,
122123
FirebaseFirestore as PublicFirestore,
123124
FirestoreDataConverter as PublicFirestoreDataConverter,
124125
GetOptions as PublicGetOptions,
@@ -518,22 +519,28 @@ export class Transaction implements PublicTransaction {
518519
): Transaction;
519520
update(
520521
documentRef: PublicDocumentReference<unknown>,
521-
field: string | ExternalFieldPath,
522+
field: string | PublicFieldPath,
522523
value: unknown,
523524
...moreFieldsAndValues: unknown[]
524525
): Transaction;
525526
update(
526527
documentRef: PublicDocumentReference<unknown>,
527-
fieldOrUpdateData: string | ExternalFieldPath | PublicUpdateData,
528+
fieldOrUpdateData: string | PublicFieldPath | PublicUpdateData,
528529
value?: unknown,
529530
...moreFieldsAndValues: unknown[]
530531
): Transaction {
531532
let ref;
532533
let parsed;
533534

535+
// For Compat types, we have to "extract" the underlying types before
536+
// performing validation.
537+
if (fieldOrUpdateData instanceof Compat) {
538+
fieldOrUpdateData = (fieldOrUpdateData as Compat<ExpFieldPath>)._delegate;
539+
}
540+
534541
if (
535542
typeof fieldOrUpdateData === 'string' ||
536-
fieldOrUpdateData instanceof ExternalFieldPath
543+
fieldOrUpdateData instanceof ExpFieldPath
537544
) {
538545
ref = validateReference(
539546
'Transaction.update',
@@ -629,24 +636,30 @@ export class WriteBatch implements PublicWriteBatch {
629636
): WriteBatch;
630637
update(
631638
documentRef: PublicDocumentReference<unknown>,
632-
field: string | ExternalFieldPath,
639+
field: string | PublicFieldPath,
633640
value: unknown,
634641
...moreFieldsAndValues: unknown[]
635642
): WriteBatch;
636643
update(
637644
documentRef: PublicDocumentReference<unknown>,
638-
fieldOrUpdateData: string | ExternalFieldPath | PublicUpdateData,
645+
fieldOrUpdateData: string | PublicFieldPath | PublicUpdateData,
639646
value?: unknown,
640647
...moreFieldsAndValues: unknown[]
641648
): WriteBatch {
642649
this.verifyNotCommitted();
643650

651+
// For Compat types, we have to "extract" the underlying types before
652+
// performing validation.
653+
if (fieldOrUpdateData instanceof Compat) {
654+
fieldOrUpdateData = (fieldOrUpdateData as Compat<ExpFieldPath>)._delegate;
655+
}
656+
644657
let ref;
645658
let parsed;
646659

647660
if (
648661
typeof fieldOrUpdateData === 'string' ||
649-
fieldOrUpdateData instanceof ExternalFieldPath
662+
fieldOrUpdateData instanceof ExpFieldPath
650663
) {
651664
ref = validateReference(
652665
'WriteBatch.update',
@@ -825,26 +838,25 @@ export class DocumentReference<T = PublicDocumentData>
825838

826839
update(value: PublicUpdateData): Promise<void>;
827840
update(
828-
field: string | ExternalFieldPath,
841+
field: string | PublicFieldPath,
829842
value: unknown,
830843
...moreFieldsAndValues: unknown[]
831844
): Promise<void>;
832845
update(
833-
fieldOrUpdateData: string | ExternalFieldPath | PublicUpdateData,
846+
fieldOrUpdateData: string | PublicFieldPath | PublicUpdateData,
834847
value?: unknown,
835848
...moreFieldsAndValues: unknown[]
836849
): Promise<void> {
837850
// For Compat types, we have to "extract" the underlying types before
838851
// performing validation.
839852
if (fieldOrUpdateData instanceof Compat) {
840-
fieldOrUpdateData = (fieldOrUpdateData as Compat<_BaseFieldPath>)
841-
._delegate;
853+
fieldOrUpdateData = (fieldOrUpdateData as Compat<ExpFieldPath>)._delegate;
842854
}
843855

844856
let parsed;
845857
if (
846858
typeof fieldOrUpdateData === 'string' ||
847-
fieldOrUpdateData instanceof _BaseFieldPath
859+
fieldOrUpdateData instanceof ExpFieldPath
848860
) {
849861
parsed = parseUpdateVarargs(
850862
this._dataReader,
@@ -1080,7 +1092,7 @@ export class DocumentSnapshot<T = PublicDocumentData>
10801092
}
10811093

10821094
get(
1083-
fieldPath: string | ExternalFieldPath,
1095+
fieldPath: string | PublicFieldPath,
10841096
options: PublicSnapshotOptions = {}
10851097
): unknown {
10861098
if (this._document) {
@@ -1556,7 +1568,7 @@ export class Query<T = PublicDocumentData> implements PublicQuery<T> {
15561568
}
15571569

15581570
where(
1559-
field: string | ExternalFieldPath,
1571+
field: string | PublicFieldPath,
15601572
opStr: PublicWhereFilterOp,
15611573
value: unknown
15621574
): PublicQuery<T> {
@@ -1578,7 +1590,7 @@ export class Query<T = PublicDocumentData> implements PublicQuery<T> {
15781590
}
15791591

15801592
orderBy(
1581-
field: string | ExternalFieldPath,
1593+
field: string | PublicFieldPath,
15821594
directionStr?: PublicOrderByDirection
15831595
): PublicQuery<T> {
15841596
let direction: Direction;

packages/firestore/src/api/field_path.ts

+9-58
Original file line numberDiff line numberDiff line change
@@ -17,52 +17,28 @@
1717

1818
import { FieldPath as PublicFieldPath } from '@firebase/firestore-types';
1919

20+
import { FieldPath as ExpFieldPath } from '../../lite/src/api/field_path';
2021
import { FieldPath as InternalFieldPath } from '../model/path';
21-
import { Code, FirestoreError } from '../util/error';
22+
import { Compat } from '../compat/compat';
2223

2324
// The objects that are a part of this API are exposed to third-parties as
2425
// compiled javascript so we want to flag our private members with a leading
2526
// underscore to discourage their use.
2627

27-
/**
28-
* A field class base class that is shared by the lite, full and legacy SDK,
29-
* which supports shared code that deals with FieldPaths.
30-
*/
31-
// Use underscore prefix to hide this class from our Public API.
32-
// eslint-disable-next-line @typescript-eslint/naming-convention
33-
export abstract class _BaseFieldPath {
34-
/** Internal representation of a Firestore field path. */
35-
readonly _internalPath: InternalFieldPath;
36-
37-
constructor(fieldNames: string[]) {
38-
for (let i = 0; i < fieldNames.length; ++i) {
39-
if (fieldNames[i].length === 0) {
40-
throw new FirestoreError(
41-
Code.INVALID_ARGUMENT,
42-
`Invalid field name at argument $(i + 1). ` +
43-
'Field names must not be empty.'
44-
);
45-
}
46-
}
47-
48-
this._internalPath = new InternalFieldPath(fieldNames);
49-
}
50-
}
51-
5228
/**
5329
* A `FieldPath` refers to a field in a document. The path may consist of a
5430
* single field name (referring to a top-level field in the document), or a list
5531
* of field names (referring to a nested field in the document).
5632
*/
57-
export class FieldPath extends _BaseFieldPath implements PublicFieldPath {
33+
export class FieldPath extends Compat<ExpFieldPath> implements PublicFieldPath {
5834
/**
5935
* Creates a FieldPath from the provided field names. If more than one field
6036
* name is provided, the path will point to a nested field in a document.
6137
*
6238
* @param fieldNames A list of field names.
6339
*/
6440
constructor(...fieldNames: string[]) {
65-
super(fieldNames);
41+
super(new ExpFieldPath(...fieldNames));
6642
}
6743

6844
static documentId(): FieldPath {
@@ -76,37 +52,12 @@ export class FieldPath extends _BaseFieldPath implements PublicFieldPath {
7652
}
7753

7854
isEqual(other: PublicFieldPath): boolean {
79-
if (!(other instanceof FieldPath)) {
55+
if (other instanceof Compat) {
56+
other = other._delegate;
57+
}
58+
if (!(other instanceof ExpFieldPath)) {
8059
return false;
8160
}
82-
return this._internalPath.isEqual(other._internalPath);
83-
}
84-
}
85-
86-
/**
87-
* Matches any characters in a field path string that are reserved.
88-
*/
89-
const RESERVED = new RegExp('[~\\*/\\[\\]]');
90-
91-
/**
92-
* Parses a field path string into a FieldPath, treating dots as separators.
93-
*/
94-
export function fromDotSeparatedString(path: string): FieldPath {
95-
const found = path.search(RESERVED);
96-
if (found >= 0) {
97-
throw new FirestoreError(
98-
Code.INVALID_ARGUMENT,
99-
`Invalid field path (${path}). Paths must not contain ` +
100-
`'~', '*', '/', '[', or ']'`
101-
);
102-
}
103-
try {
104-
return new FieldPath(...path.split('.'));
105-
} catch (e) {
106-
throw new FirestoreError(
107-
Code.INVALID_ARGUMENT,
108-
`Invalid field path (${path}). Paths must not be empty, ` +
109-
`begin with '.', end with '.', or contain '..'`
110-
);
61+
return this._delegate._internalPath.isEqual(other._internalPath);
11162
}
11263
}

0 commit comments

Comments
 (0)