15
15
* limitations under the License.
16
16
*/
17
17
18
- import { Blob } from '../api/blob' ;
19
- import { GeoPoint } from '../api/geo_point' ;
20
- import { Timestamp } from '../api/timestamp' ;
21
- import { DatabaseId } from '../core/database_info' ;
18
+ import { Blob } from '../api/blob' ;
19
+ import { GeoPoint } from '../api/geo_point' ;
20
+ import { Timestamp } from '../api/timestamp' ;
21
+ import { DatabaseId } from '../core/database_info' ;
22
22
import {
23
23
Bound ,
24
24
Direction ,
@@ -29,12 +29,12 @@ import {
29
29
OrderBy ,
30
30
Query
31
31
} from '../core/query' ;
32
- import { SnapshotVersion } from '../core/snapshot_version' ;
33
- import { Target } from '../core/target' ;
34
- import { TargetId } from '../core/types' ;
35
- import { TargetData , TargetPurpose } from '../local/target_data' ;
36
- import { Document , MaybeDocument , NoDocument } from '../model/document' ;
37
- import { DocumentKey } from '../model/document_key' ;
32
+ import { SnapshotVersion } from '../core/snapshot_version' ;
33
+ import { Target } from '../core/target' ;
34
+ import { TargetId } from '../core/types' ;
35
+ import { TargetData , TargetPurpose } from '../local/target_data' ;
36
+ import { Document , MaybeDocument , NoDocument } from '../model/document' ;
37
+ import { DocumentKey } from '../model/document_key' ;
38
38
import * as fieldValue from '../model/field_value' ;
39
39
import {
40
40
DeleteMutation ,
@@ -48,13 +48,13 @@ import {
48
48
TransformMutation ,
49
49
VerifyMutation
50
50
} from '../model/mutation' ;
51
- import { FieldPath , ResourcePath } from '../model/path' ;
51
+ import { FieldPath , ResourcePath } from '../model/path' ;
52
52
import * as api from '../protos/firestore_proto_api' ;
53
- import { assert , fail } from '../util/assert' ;
54
- import { Code , FirestoreError } from '../util/error' ;
53
+ import { assert , fail } from '../util/assert' ;
54
+ import { Code , FirestoreError } from '../util/error' ;
55
55
import * as obj from '../util/obj' ;
56
- import { ByteString } from '../util/byte_string' ;
57
- import * as typeUtils from '../util/types' ;
56
+ import { ByteString } from '../util/byte_string' ;
57
+ import { isNullOrUndefined } from '../util/types' ;
58
58
59
59
import {
60
60
ArrayRemoveTransformOperation ,
@@ -63,8 +63,8 @@ import {
63
63
ServerTimestampTransform ,
64
64
TransformOperation
65
65
} from '../model/transform_operation' ;
66
- import { ExistenceFilter } from './existence_filter' ;
67
- import { mapCodeFromRpcCode , mapRpcCodeFromCode } from './rpc_error' ;
66
+ import { ExistenceFilter } from './existence_filter' ;
67
+ import { mapCodeFromRpcCode , mapRpcCodeFromCode } from './rpc_error' ;
68
68
import {
69
69
DocumentWatchChange ,
70
70
ExistenceFilterChange ,
@@ -99,15 +99,13 @@ const OPERATORS = (() => {
99
99
} ) ( ) ;
100
100
101
101
function assertPresent ( value : unknown , description : string ) : asserts value {
102
- assert ( ! typeUtils . isNullOrUndefined ( value ) , description + ' is missing' ) ;
102
+ assert ( ! isNullOrUndefined ( value ) , description + ' is missing' ) ;
103
103
}
104
104
105
- // This is a supplement to the generated proto interfaces, which fail to account
106
- // for the fact that a timestamp may be encoded as either a string OR this.
107
- interface TimestampProto {
108
- seconds ?: string | number ;
109
- nanos ?: number ;
110
- }
105
+ // Denotes the possible representations for timestamps in the Value type.
106
+ export type TimestampValue =
107
+ | string
108
+ | { seconds ?: string | number ; nanos ?: number } ;
111
109
112
110
export interface SerializerOptions {
113
111
/**
@@ -148,46 +146,33 @@ export class JsonProtoSerializer {
148
146
* our generated proto interfaces say Int32Value must be. But GRPC actually
149
147
* expects a { value: <number> } struct.
150
148
*/
151
- private toInt32Value ( val : number | null ) : number | null {
152
- if ( this . options . useProto3Json || typeUtils . isNullOrUndefined ( val ) ) {
149
+ private toInt32Value ( val : number | null ) : number | { value : number } | null {
150
+ if ( this . options . useProto3Json || isNullOrUndefined ( val ) ) {
153
151
return val ;
154
152
} else {
155
- // ProtobufJS requires that we wrap Int32Values.
156
- // Use any because we need to match generated Proto types.
157
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
- return { value : val } as any ;
153
+ return { value : val } ;
159
154
}
160
155
}
161
156
162
157
/**
163
158
* Returns a number (or null) from a google.protobuf.Int32Value proto.
164
- * DO NOT USE THIS FOR ANYTHING ELSE.
165
- * This method cheats. It's typed as accepting "number" because that's what
166
- * our generated proto interfaces say Int32Value must be, but it actually
167
- * accepts { value: number } to match our serialization in toInt32Value().
168
159
*/
169
- private fromInt32Value ( val : number | undefined ) : number | null {
160
+ private fromInt32Value (
161
+ val : number | { value : number } | undefined
162
+ ) : number | null {
170
163
let result ;
171
164
if ( typeof val === 'object' ) {
172
- // Use any because we need to match generated Proto types.
173
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
174
- result = ( val as any ) . value ;
165
+ result = val . value ;
175
166
} else {
176
- // We accept raw numbers (without the {value: ... } wrapper) for
177
- // compatibility with legacy persisted data.
178
167
result = val ;
179
168
}
180
- return typeUtils . isNullOrUndefined ( result ) ? null : result ;
169
+ return isNullOrUndefined ( result ) ? null : result ;
181
170
}
182
171
183
172
/**
184
173
* Returns a value for a Date that's appropriate to put into a proto.
185
- * DO NOT USE THIS FOR ANYTHING ELSE.
186
- * This method cheats. It's typed as returning "string" because that's what
187
- * our generated proto interfaces say dates must be. But it's easier and safer
188
- * to actually return a Timestamp proto.
189
174
*/
190
- private toTimestamp ( timestamp : Timestamp ) : string {
175
+ private toTimestamp ( timestamp : Timestamp ) : TimestampValue {
191
176
if ( this . options . useProto3Json ) {
192
177
// Serialize to ISO-8601 date format, but with full nano resolution.
193
178
// Since JS Date has only millis, let's only use it for the seconds and
@@ -208,25 +193,21 @@ export class JsonProtoSerializer {
208
193
}
209
194
}
210
195
211
- private fromTimestamp ( date : string | TimestampProto ) : Timestamp {
196
+ private fromTimestamp ( date : TimestampValue ) : Timestamp {
212
197
const timestamp = normalizeTimestamp ( date ) ;
213
198
return new Timestamp ( timestamp . seconds , timestamp . nanos ) ;
214
199
}
215
200
216
201
/**
217
202
* Returns a value for bytes that's appropriate to put in a proto.
218
- * DO NOT USE THIS FOR ANYTHING ELSE.
219
- * This method cheats. It's typed as returning "string" because that's what
220
- * our generated proto interfaces say bytes must be. But it should return
221
- * an Uint8Array in Node.
222
203
*
223
204
* Visible for testing.
224
205
*/
225
- toBytes ( bytes : Blob | ByteString ) : string {
206
+ toBytes ( bytes : Blob | ByteString ) : string | Uint8Array {
226
207
if ( this . options . useProto3Json ) {
227
208
return bytes . toBase64 ( ) ;
228
209
} else {
229
- return ( bytes . toUint8Array ( ) as unknown ) as string ;
210
+ return bytes . toUint8Array ( ) ;
230
211
}
231
212
}
232
213
@@ -249,11 +230,11 @@ export class JsonProtoSerializer {
249
230
}
250
231
}
251
232
252
- toVersion ( version : SnapshotVersion ) : string {
233
+ toVersion ( version : SnapshotVersion ) : TimestampValue {
253
234
return this . toTimestamp ( version . toTimestamp ( ) ) ;
254
235
}
255
236
256
- fromVersion ( version : string ) : SnapshotVersion {
237
+ fromVersion ( version : TimestampValue ) : SnapshotVersion {
257
238
assert ( ! ! version , "Trying to deserialize version that isn't set" ) ;
258
239
return SnapshotVersion . fromTimestamp ( this . fromTimestamp ( version ) ) ;
259
240
}
@@ -844,7 +825,7 @@ export class JsonProtoSerializer {
844
825
845
826
private fromWriteResult (
846
827
proto : api . WriteResult ,
847
- commitTime : string
828
+ commitTime : TimestampValue
848
829
) : MutationResult {
849
830
// NOTE: Deletes don't have an updateTime.
850
831
let version = proto . updateTime
@@ -871,7 +852,7 @@ export class JsonProtoSerializer {
871
852
872
853
fromWriteResults (
873
854
protos : api . WriteResult [ ] | undefined ,
874
- commitTime ?: string
855
+ commitTime ?: TimestampValue
875
856
) : MutationResult [ ] {
876
857
if ( protos && protos . length > 0 ) {
877
858
assert (
0 commit comments