Skip to content

Commit 872bd1c

Browse files
committed
feat: better defaults for wait and reset
BREAKING CHANGE: `wait` option now defaults to `true` to better align with SSR. Similarly, the `reset` option now defaults to `false` to better align with declarative usage of `useDocument()` and others. If you want to keep the old behavior, you can still override the defaults globally (refer to global options in the docs).
1 parent 8db64ea commit 872bd1c

13 files changed

+140
-128
lines changed

src/database/optionsApi.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
bindAsObject,
88
rtdbOptions,
99
_DatabaseRefOptions,
10+
_GlobalDatabaseRefOptions,
1011
} from './subscribe'
1112

1213
/**
@@ -21,20 +22,17 @@ function getRef(refOrQuery: DatabaseReference | Query): DatabaseReference {
2122
/**
2223
* Options for the Firebase Database Plugin that enables the Options API such as `$rtdbBind` and `$rtdbUnbind`.
2324
*/
24-
export interface DatabasePluginOptions {
25+
export interface DatabasePluginOptions
26+
extends Partial<_GlobalDatabaseRefOptions> {
2527
bindName?: string
2628
unbindName?: string
27-
serialize?: _DatabaseRefOptions['serialize']
28-
reset?: _DatabaseRefOptions['reset']
29-
wait?: _DatabaseRefOptions['wait']
3029
}
3130

32-
const databasePluginDefaults: Readonly<Required<DatabasePluginOptions>> = {
31+
const databasePluginDefaults: Readonly<
32+
Required<Omit<DatabasePluginOptions, keyof _GlobalDatabaseRefOptions>>
33+
> = {
3334
bindName: '$rtdbBind',
3435
unbindName: '$rtdbUnbind',
35-
serialize: rtdbOptions.serialize,
36-
reset: rtdbOptions.reset,
37-
wait: rtdbOptions.wait,
3836
}
3937

4038
declare module '@vue/runtime-core' {

src/database/subscribe.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
indexForKey,
44
DatabaseSnapshotSerializer,
55
} from './utils'
6-
import { OperationsType, ResetOption } from '../shared'
6+
import { OperationsType, ResetOption, _DataSourceOptions } from '../shared'
77
import { ref, Ref, unref } from 'vue-demi'
88
import type { Query, DatabaseReference } from 'firebase/database'
99
import {
@@ -15,24 +15,29 @@ import {
1515
} from 'firebase/database'
1616

1717
// TODO: rename to match where it's used
18-
export interface _DatabaseRefOptions {
19-
reset?: ResetOption
18+
export interface _DatabaseRefOptions extends _DataSourceOptions {
2019
serialize?: DatabaseSnapshotSerializer
21-
wait?: boolean
2220

2321
initialValue?: unknown
2422
}
2523

2624
export interface _GlobalDatabaseRefOptions extends _DatabaseRefOptions {
25+
/**
26+
* @defaultValue `false`
27+
*/
2728
reset: ResetOption
28-
serialize: DatabaseSnapshotSerializer
29+
/**
30+
* @defaultValue `true`
31+
*/
2932
wait: boolean
33+
34+
serialize: DatabaseSnapshotSerializer
3035
}
3136

3237
const DEFAULT_OPTIONS: _GlobalDatabaseRefOptions = {
33-
reset: true,
38+
reset: false,
3439
serialize: createRecordFromDatabaseSnapshot,
35-
wait: false,
40+
wait: true,
3641
}
3742

3843
// TODO: rename rtdbDefaults databaseDefaults

src/firestore/index.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
bindCollection,
3232
bindDocument,
3333
firestoreOptions,
34-
FirestoreOptions,
34+
FirestoreRefOptions,
3535
} from './subscribe'
3636

3737
export const ops: OperationsType = {
@@ -42,7 +42,10 @@ export const ops: OperationsType = {
4242

4343
type UnbindType = ReturnType<typeof bindCollection | typeof bindDocument>
4444

45-
export interface _UseFirestoreRefOptions extends FirestoreOptions {
45+
export interface _UseFirestoreRefOptions extends FirestoreRefOptions {
46+
/**
47+
* Use the `target` ref instead of creating one.
48+
*/
4649
target?: Ref<unknown>
4750
}
4851

@@ -81,8 +84,8 @@ export function _useFirestoreRef(
8184
}
8285

8386
_unbind = (isDocumentRef(docRefValue) ? bindDocument : bindCollection)(
87+
// @ts-expect-error: cannot type with the ternary
8488
data,
85-
// @ts-expect-error: the type is good because of the ternary
8689
docRefValue,
8790
ops,
8891
resolve,
@@ -246,15 +249,15 @@ export function internalUnbind(
246249
unbinds:
247250
| Record<string, ReturnType<typeof bindCollection | typeof bindDocument>>
248251
| undefined,
249-
reset?: FirestoreOptions['reset']
252+
reset?: FirestoreRefOptions['reset']
250253
) {
251254
if (unbinds && unbinds[key]) {
252255
unbinds[key](reset)
253256
delete unbinds[key]
254257
}
255258
}
256259

257-
export const unbind = (target: Ref, reset?: FirestoreOptions['reset']) =>
260+
export const unbind = (target: Ref, reset?: FirestoreRefOptions['reset']) =>
258261
internalUnbind('', firestoreUnbinds.get(target), reset)
259262

260263
/**

src/firestore/optionsApi.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import {
1010
bindCollection,
1111
bindDocument,
1212
firestoreOptions,
13-
FirestoreOptions,
13+
FirestoreRefOptions,
14+
_GlobalFirestoreRefOptions,
1415
} from './subscribe'
1516
import { internalUnbind, _useFirestoreRef } from '.'
17+
import { ResetOption } from '../shared'
1618

1719
export type FirestoreOption = VueFirestoreObject | (() => VueFirestoreObject)
1820

@@ -32,20 +34,17 @@ export const firestoreUnbinds = new WeakMap<
3234
* Options for the Firebase Database Plugin that enables the Options API such as `$firestoreBind` and
3335
* `$firestoreUnbind`.
3436
*/
35-
export interface FirestorePluginOptions {
37+
export interface FirestorePluginOptions
38+
extends Partial<_GlobalFirestoreRefOptions> {
3639
bindName?: string
3740
unbindName?: string
38-
converter?: FirestoreOptions['converter']
39-
reset?: FirestoreOptions['reset']
40-
wait?: FirestoreOptions['wait']
4141
}
4242

43-
const firestorePluginDefaults: Readonly<Required<FirestorePluginOptions>> = {
43+
const firestorePluginDefaults: Readonly<
44+
Required<Omit<FirestorePluginOptions, keyof _GlobalFirestoreRefOptions>>
45+
> = {
4446
bindName: '$firestoreBind',
4547
unbindName: '$firestoreUnbind',
46-
converter: firestoreOptions.converter,
47-
reset: firestoreOptions.reset,
48-
wait: firestoreOptions.wait,
4948
}
5049

5150
/**
@@ -76,7 +75,7 @@ export const firestorePlugin = function firestorePlugin(
7675

7776
GlobalTarget[unbindName] = function firestoreUnbind(
7877
key: string,
79-
reset?: FirestoreOptions['reset']
78+
reset?: FirestoreRefOptions['reset']
8079
) {
8180
internalUnbind(key, firestoreUnbinds.get(this), reset)
8281
delete this.$firestoreRefs[key]
@@ -86,7 +85,7 @@ export const firestorePlugin = function firestorePlugin(
8685
this: ComponentPublicInstance,
8786
key: string,
8887
docOrCollectionRef: Query | CollectionReference | DocumentReference,
89-
userOptions?: FirestoreOptions
88+
userOptions?: FirestoreRefOptions
9089
) {
9190
const options = Object.assign({}, globalOptions, userOptions)
9291
const target = toRef(this.$data as any, key)
@@ -163,26 +162,27 @@ declare module '@vue/runtime-core' {
163162
name: string,
164163
// TODO: create proper overloads with generics like in the composition API
165164
reference: Query<unknown> | CollectionReference<unknown>,
166-
options?: FirestoreOptions
165+
options?: FirestoreRefOptions
166+
// TODO: match the promise with the type of internalBind
167167
): Promise<DocumentData[]>
168168

169169
$firestoreBind(
170170
name: string,
171171
// TODO: create proper overloads with generics like in the composition API
172172
reference: DocumentReference<unknown>,
173-
options?: FirestoreOptions
173+
options?: FirestoreRefOptions
174174
): Promise<DocumentData>
175175

176176
/**
177177
* Unbinds a bound reference
178178
*/
179-
$firestoreUnbind: (name: string, reset?: FirestoreOptions['reset']) => void
179+
$firestoreUnbind: (name: string, reset?: ResetOption) => void
180180

181181
/**
182182
* Bound firestore references
183183
*/
184184
$firestoreRefs: Readonly<
185-
Record<string, DocumentReference | CollectionReference>
185+
Record<string, DocumentReference<unknown> | CollectionReference<unknown>>
186186
>
187187
// _firestoreSources: Readonly<
188188
// Record<string, CollectionReference | Query | DocumentReference>

src/firestore/subscribe.ts

+45-39
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
OperationsType,
66
_MaybeRef,
77
ResetOption,
8+
_DataSourceOptions,
89
} from '../shared'
910
import { ref, Ref, unref } from 'vue-demi'
1011
import type {
@@ -20,12 +21,15 @@ import type {
2021
} from 'firebase/firestore'
2122
import { onSnapshot } from 'firebase/firestore'
2223

23-
export interface FirestoreOptions {
24+
/**
25+
* Options when binding a Firestore document or collection.
26+
*/
27+
export interface FirestoreRefOptions extends _DataSourceOptions {
28+
/**
29+
* The maximum depth to bind nested refs. A nested ref that isn't bound will stay as the ref path while a bound ref
30+
* will contain the same data as if the ref was bound directly.
31+
*/
2432
maxRefDepth?: number
25-
reset?: ResetOption
26-
27-
// FIXME: should only be possible in global options
28-
converter?: FirestoreDataConverter<unknown>
2933

3034
initialValue?: unknown
3135

@@ -35,26 +39,38 @@ export interface FirestoreOptions {
3539
* @inheritDoc {SnapshotListenOptions}
3640
*/
3741
snapshotListenOptions?: SnapshotListenOptions
38-
39-
wait?: boolean
4042
}
4143

42-
export interface _GlobalFirestoreOptions extends FirestoreOptions {
43-
maxRefDepth: number
44+
/**
45+
* Type of the global options for firestore refs. Some values cannot be `undefined`.
46+
* @internal
47+
*/
48+
export interface _GlobalFirestoreRefOptions extends FirestoreRefOptions {
49+
/**
50+
* @defaultValue `false`
51+
*/
4452
reset: ResetOption
45-
converter: FirestoreDataConverter<unknown>
53+
/**
54+
* @defaultValue `true`
55+
*/
4656
wait: boolean
47-
}
4857

49-
export interface VueFireFirestoreOptions extends FirestoreOptions {
50-
converter?: FirestoreDataConverter<unknown>
58+
/**
59+
* @defaultValue `2`
60+
*/
61+
maxRefDepth: number
62+
63+
/**
64+
* Default Firestore converter to use with snapshots.
65+
*/
66+
converter: FirestoreDataConverter<unknown>
5167
}
5268

53-
const DEFAULT_OPTIONS: _GlobalFirestoreOptions = {
69+
const DEFAULT_OPTIONS: _GlobalFirestoreRefOptions = {
70+
reset: false,
71+
wait: true,
5472
maxRefDepth: 2,
55-
reset: true,
5673
converter: firestoreDefaultConverter,
57-
wait: false,
5874
}
5975
export { DEFAULT_OPTIONS as firestoreOptions }
6076

@@ -74,7 +90,7 @@ function unsubscribeAll(subs: Record<string, FirestoreSubscription>) {
7490
}
7591

7692
function updateDataFromDocumentSnapshot<T>(
77-
options: _GlobalFirestoreOptions,
93+
options: _GlobalFirestoreRefOptions,
7894
target: Ref<T>,
7995
path: string,
8096
snapshot: DocumentSnapshot<T>,
@@ -94,8 +110,8 @@ function updateDataFromDocumentSnapshot<T>(
94110
subscribeToRefs(options, target, path, subs, refs, ops, depth, resolve)
95111
}
96112

97-
interface SubscribeToDocumentParamater {
98-
target: CommonBindOptionsParameter['target']
113+
interface SubscribeToDocumentParameter {
114+
target: Ref<unknown>
99115
path: string
100116
depth: number
101117
resolve: () => void
@@ -104,8 +120,8 @@ interface SubscribeToDocumentParamater {
104120
}
105121

106122
function subscribeToDocument(
107-
{ ref, target, path, depth, resolve, ops }: SubscribeToDocumentParamater,
108-
options: _GlobalFirestoreOptions
123+
{ ref, target, path, depth, resolve, ops }: SubscribeToDocumentParameter,
124+
options: _GlobalFirestoreRefOptions
109125
) {
110126
const subs = Object.create(null)
111127
const unbind = onSnapshot(ref, (snapshot) => {
@@ -132,22 +148,12 @@ function subscribeToDocument(
132148
}
133149
}
134150

135-
// interface SubscribeToRefsParameter {
136-
// subs: Record<string, FirestoreSubscription>
137-
// target: CommonBindOptionsParameter['vm']
138-
// refs: Record<string, DocumentReference>
139-
// path: string | number
140-
// depth: number
141-
// resolve: CommonBindOptionsParameter['resolve']
142-
// ops: CommonBindOptionsParameter['ops']
143-
// }
144-
145151
// NOTE: not convinced by the naming of subscribeToRefs and subscribeToDocument
146152
// first one is calling the other on every ref and subscribeToDocument may call
147153
// updateDataFromDocumentSnapshot which may call subscribeToRefs as well
148154
function subscribeToRefs(
149-
options: _GlobalFirestoreOptions,
150-
target: CommonBindOptionsParameter['target'],
155+
options: _GlobalFirestoreRefOptions,
156+
target: Ref<unknown>,
151157
path: string | number,
152158
subs: Record<string, FirestoreSubscription>,
153159
refs: Record<string, DocumentReference>,
@@ -219,12 +225,12 @@ interface CommonBindOptionsParameter {
219225
}
220226

221227
export function bindCollection<T = unknown>(
222-
target: CommonBindOptionsParameter['target'],
228+
target: Ref<unknown[]>,
223229
collection: CollectionReference<T> | Query<T>,
224230
ops: CommonBindOptionsParameter['ops'],
225231
resolve: CommonBindOptionsParameter['resolve'],
226232
reject: CommonBindOptionsParameter['reject'],
227-
extraOptions?: FirestoreOptions
233+
extraOptions?: FirestoreRefOptions
228234
) {
229235
// FIXME: can be removed now
230236
const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions) // fill default values
@@ -348,7 +354,7 @@ export function bindCollection<T = unknown>(
348354
reject
349355
)
350356

351-
return (reset?: FirestoreOptions['reset']) => {
357+
return (reset?: FirestoreRefOptions['reset']) => {
352358
unbind()
353359
if (reset !== false) {
354360
const value = typeof reset === 'function' ? reset() : []
@@ -368,12 +374,12 @@ interface BindDocumentParameter extends CommonBindOptionsParameter {
368374
* @param extraOptions
369375
*/
370376
export function bindDocument<T>(
371-
target: BindDocumentParameter['target'],
377+
target: Ref<unknown>,
372378
document: DocumentReference<T>,
373379
ops: BindDocumentParameter['ops'],
374380
resolve: BindDocumentParameter['resolve'],
375381
reject: BindDocumentParameter['reject'],
376-
extraOptions?: FirestoreOptions
382+
extraOptions?: FirestoreRefOptions
377383
) {
378384
const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions) // fill default values
379385
const key = 'value'
@@ -406,7 +412,7 @@ export function bindDocument<T>(
406412
reject
407413
)
408414

409-
return (reset?: FirestoreOptions['reset']) => {
415+
return (reset?: FirestoreRefOptions['reset']) => {
410416
_unbind()
411417
if (reset !== false) {
412418
const value = typeof reset === 'function' ? reset() : null

0 commit comments

Comments
 (0)