Skip to content

Commit 2eab3fc

Browse files
committed
feat: findDefaults + resolveFindOptions
1 parent 1456401 commit 2eab3fc

File tree

18 files changed

+198
-68
lines changed

18 files changed

+198
-68
lines changed

docs/guide/data/query.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,21 @@ The cache will automatically resolve the relations as soon as the data is availa
535535

536536
Plugins hooked on the `fetchRelations` hook will also be called to potentially fetch the data of the relations. See [Plugin hooks](../plugin/hooks.md#fetching-relations) for more details.
537537

538+
## Default find options <Badge text="New in v0.8.3" />
539+
540+
You can set default find options for all queries in the store by using the `findDefaults` option when creating the store:
541+
542+
```ts
543+
const store = createStore({
544+
schema,
545+
plugins,
546+
findDefaults: {
547+
fetchPolicy: 'cache-and-fetch',
548+
// Other default find options...
549+
},
550+
})
551+
```
552+
538553
## Customizing Find Options Types <Badge text="Changed in v0.7" type="warning" />
539554

540555
You can customize the `FindOptions` type used in the `first` and `many` query builder methods and in the `peek*`/`find*` methods by declaring a module augmentation for `@rstore/vue` and extending the `FindOptions` interface.

docs/guide/plugin/hooks.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,3 +972,18 @@ hook('afterFetch', (payload) => {
972972
)
973973
})
974974
```
975+
976+
### resolveFindOptions <Badge text="New in v0.8.3" />
977+
978+
```ts
979+
hook('resolveFindOptions', (payload) => {
980+
console.log(
981+
payload.store,
982+
payload.meta,
983+
payload.collection, // The current collection
984+
payload.many, // Boolean indicating if the query is for many items or one item
985+
payload.findOptions, // The find options passed to the query, such as filter or params
986+
payload.updateFindOptions, // A function to update the find options
987+
)
988+
})
989+
```

packages/core/src/query/findFirst.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,8 @@ async function _findFirst<
6464
}
6565
: keyOrOptions
6666

67-
if (findOptions.meta) {
68-
Object.assign(meta, findOptions.meta)
69-
}
70-
71-
const fetchPolicy = store.$getFetchPolicy(findOptions?.fetchPolicy)
72-
73-
findOptions = {
74-
...findOptions,
75-
fetchPolicy,
76-
}
67+
findOptions = store.$resolveFindOptions(collection, findOptions, false, meta)
68+
const fetchPolicy = findOptions.fetchPolicy
7769

7870
let result: any
7971
let marker: string | undefined

packages/core/src/query/findMany.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,8 @@ async function _findMany<
5959
meta ??= {}
6060
findOptions ??= {}
6161

62-
if (findOptions.meta) {
63-
Object.assign(meta, findOptions.meta)
64-
}
65-
66-
const fetchPolicy = store.$getFetchPolicy(findOptions.fetchPolicy)
67-
68-
findOptions = {
69-
...findOptions,
70-
fetchPolicy,
71-
}
62+
findOptions = store.$resolveFindOptions(collection, findOptions, true, meta)
63+
const fetchPolicy = findOptions.fetchPolicy
7264

7365
let result: any[] | undefined
7466
let marker: string | undefined

packages/core/src/query/peekFirst.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,16 @@ export function peekFirst<
3030
}: PeekFirstOptions<TCollection, TCollectionDefaults, TSchema>): QueryResult<WrappedItem<TCollection, TCollectionDefaults, TSchema> | null> {
3131
meta ??= {}
3232

33-
const findOptions: FindFirstOptions<TCollection, TCollectionDefaults, TSchema> = typeof keyOrOptions === 'string' || typeof keyOrOptions === 'number'
33+
let findOptions: FindFirstOptions<TCollection, TCollectionDefaults, TSchema> = typeof keyOrOptions === 'string' || typeof keyOrOptions === 'number'
3434
? {
3535
key: keyOrOptions,
3636
}
3737
: keyOrOptions
3838

39-
const key = findOptions?.key
40-
41-
if (findOptions.meta) {
42-
Object.assign(meta, findOptions.meta)
43-
}
39+
findOptions = store.$resolveFindOptions(collection, findOptions, false, meta)
40+
const fetchPolicy = findOptions.fetchPolicy
4441

45-
const fetchPolicy = store.$getFetchPolicy(findOptions?.fetchPolicy)
42+
const key = findOptions?.key
4643

4744
if (force || shouldReadCacheFromFetchPolicy(fetchPolicy)) {
4845
let result: any

packages/core/src/query/peekMany.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ export function peekMany<
3030
}: PeekManyOptions<TCollection, TCollectionDefaults, TSchema>): QueryResult<Array<WrappedItem<TCollection, TCollectionDefaults, TSchema>>> {
3131
meta ??= {}
3232

33-
if (findOptions?.meta) {
34-
Object.assign(meta, findOptions.meta)
35-
}
33+
findOptions = store.$resolveFindOptions(collection, findOptions ?? {}, true, meta)
34+
const fetchPolicy = findOptions.fetchPolicy
3635

37-
const fetchPolicy = store.$getFetchPolicy(findOptions?.fetchPolicy)
3836
if (force || shouldReadCacheFromFetchPolicy(fetchPolicy)) {
3937
let marker: string | undefined = defaultMarker(collection, findOptions)
4038
let overrideFilter: ((item: ResolvedCollectionItemBase<TCollection, TCollectionDefaults, TSchema>) => boolean) | undefined

packages/core/src/store.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export interface CreateStoreCoreOptions<
2020
syncImmediately?: boolean
2121
}
2222

23+
const resolvedFindOptionsMarker = Symbol('resolvedFindOptions')
24+
2325
export async function createStoreCore<
2426
TSchema extends StoreSchema = StoreSchema,
2527
TCollectionDefaults extends CollectionDefaults = CollectionDefaults,
@@ -38,8 +40,33 @@ export async function createStoreCore<
3840
$plugins: sortPlugins(optionPlugins.map(p => ({ ...p, hooks: {} }))),
3941
$hooks: options.hooks,
4042
$findDefaults: options.findDefaults ?? {},
41-
$getFetchPolicy(value) {
42-
return value ?? store.$findDefaults.fetchPolicy ?? defaultFetchPolicy
43+
$resolveFindOptions(collection, options, many, meta) {
44+
if ((options as any)[resolvedFindOptionsMarker]) {
45+
return options as any
46+
}
47+
const resolvedOptions: FindOptions<any, any, any> = {
48+
...store.$findDefaults,
49+
...options,
50+
fetchPolicy: options.fetchPolicy ?? store.$findDefaults.fetchPolicy ?? defaultFetchPolicy,
51+
}
52+
store.$hooks.callHookSync('resolveFindOptions', {
53+
store: store as unknown as GlobalStoreType,
54+
collection,
55+
many,
56+
meta,
57+
findOptions: resolvedOptions,
58+
updateFindOptions: (newFindOptions: any) => {
59+
Object.assign(resolvedOptions, newFindOptions)
60+
},
61+
})
62+
if (resolvedOptions.meta) {
63+
Object.assign(meta, resolvedOptions.meta)
64+
}
65+
Object.defineProperty(resolvedOptions, resolvedFindOptionsMarker, {
66+
value: true,
67+
enumerable: false,
68+
})
69+
return resolvedOptions
4370
},
4471
$processItemParsing(collection, item) {
4572
store.$hooks.callHookSync('parseItem', {

packages/core/test/mutation/updateMany.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ describe('updateMany', () => {
3232
$mutationHistory: [],
3333
$processItemParsing: vi.fn(),
3434
$processItemSerialization: vi.fn(),
35-
$getFetchPolicy: vi.fn(() => 'cache-first'),
35+
$resolveFindOptions: (collection: any, options: any) => ({
36+
fetchPolicy: 'cache-first',
37+
...options,
38+
}),
3639
} as unknown as StoreCore<StoreSchema, CollectionDefaults>
3740

3841
mockCollection = {

packages/core/test/query/findFirst.spec.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ describe('findFirst', () => {
4848
}),
4949
},
5050
$hooks: createHooks(),
51-
$getFetchPolicy: () => 'cache-first',
51+
$resolveFindOptions: (collection: any, options: any) => ({
52+
fetchPolicy: 'cache-first',
53+
...options,
54+
}),
5255
$processItemParsing: vi.fn(),
5356
$dedupePromises: new Map(),
5457
} as any
@@ -105,15 +108,17 @@ describe('findFirst', () => {
105108
})
106109

107110
it('should write item to cache if fetch policy allows', async () => {
108-
mockStore.$getFetchPolicy = () => 'cache-and-fetch'
109111
mockStore.$hooks.hook('fetchFirst', (payload) => {
110112
payload.setResult({ id: '42' })
111113
})
112114

113115
const result = await findFirst({
114116
store: mockStore,
115117
collection,
116-
findOptions: '42',
118+
findOptions: {
119+
key: '42',
120+
fetchPolicy: 'cache-and-fetch',
121+
},
117122
})
118123

119124
expect(mockStore.$cache.writeItem).toHaveBeenCalledWith(expect.objectContaining({
@@ -124,29 +129,33 @@ describe('findFirst', () => {
124129
})
125130

126131
it('should not write item to cache if fetch policy is no-cache', async () => {
127-
mockStore.$getFetchPolicy = () => 'no-cache'
128132
mockStore.$hooks.hook('fetchFirst', (payload) => {
129133
payload.setResult({ id: '1' })
130134
})
131135
await findFirst({
132136
store: mockStore,
133137
collection,
134-
findOptions: '1',
138+
findOptions: {
139+
key: '1',
140+
fetchPolicy: 'no-cache',
141+
},
135142
})
136143

137144
expect(mockStore.$cache.writeItem).not.toHaveBeenCalled()
138145
})
139146

140147
it('should wrap item with noCache if fetch policy is no-cache', async () => {
141-
mockStore.$getFetchPolicy = () => 'no-cache'
142148
mockStore.$hooks.hook('fetchFirst', (payload) => {
143149
payload.setResult({ id: '1' })
144150
})
145151

146152
await findFirst({
147153
store: mockStore,
148154
collection,
149-
findOptions: '1',
155+
findOptions: {
156+
key: '1',
157+
fetchPolicy: 'no-cache',
158+
},
150159
})
151160

152161
expect(mockStore.$cache.wrapItem).toHaveBeenCalledOnce()

packages/core/test/query/findMany.spec.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ describe('findMany', () => {
4444
},
4545
},
4646
$hooks: createHooks(),
47-
$getFetchPolicy: () => 'cache-first',
47+
$resolveFindOptions: (collection: any, options: any) => ({
48+
fetchPolicy: 'cache-first',
49+
...options,
50+
}),
4851
$processItemParsing: vi.fn(),
4952
$dedupePromises: new Map(),
5053
} as any
@@ -95,7 +98,6 @@ describe('findMany', () => {
9598
})
9699

97100
it('should write items to cache if fetch policy allows', async () => {
98-
mockStore.$getFetchPolicy = () => 'cache-and-fetch'
99101
mockStore.$hooks.hook('fetchMany', (payload) => {
100102
payload.setResult([{ id: '42', name: 'Fetched Item' }])
101103
})
@@ -107,6 +109,7 @@ describe('findMany', () => {
107109
params: {
108110
email: '42',
109111
},
112+
fetchPolicy: 'cache-and-fetch',
110113
},
111114
})
112115

@@ -118,14 +121,14 @@ describe('findMany', () => {
118121
})
119122

120123
it('should not write items to cache if fetch policy is no-cache', async () => {
121-
mockStore.$getFetchPolicy = () => 'no-cache'
122124
await findMany({
123125
store: mockStore,
124126
collection,
125127
findOptions: {
126128
params: {
127129
email: '42',
128130
},
131+
fetchPolicy: 'no-cache',
129132
},
130133
})
131134

0 commit comments

Comments
 (0)