Skip to content

Commit 105aa09

Browse files
feat: watch language ref or getter by default
1 parent 9b04c3f commit 105aa09

File tree

6 files changed

+70
-37
lines changed

6 files changed

+70
-37
lines changed

docs/api/use-kql.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type UseKqlOptions<T> = AsyncDataOptions<T> & Pick<
2929
/**
3030
* Language code to fetch data for in multi-language Kirby setups.
3131
*/
32-
language?: string
32+
language?: MaybeRefOrGetter<string>
3333
/**
3434
* Skip the Nuxt server proxy and fetch directly from the API.
3535
* Requires `client` to be enabled in the module options as well.
@@ -41,6 +41,12 @@ type UseKqlOptions<T> = AsyncDataOptions<T> & Pick<
4141
* @default true
4242
*/
4343
cache?: boolean
44+
/**
45+
* Watch an array of reactive sources and auto-refresh the fetch result when they change.
46+
* Query and language are watched by default. You can completely ignore reactive sources by using `watch: false`.
47+
* @default undefined
48+
*/
49+
watch?: (WatchSource<unknown> | object)[] | false
4450
}
4551
```
4652

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
},
5252
"dependencies": {
5353
"@nuxt/kit": "^3.7.3",
54-
"@vueuse/core": "^10.4.1",
54+
"@vueuse/core": "^10",
5555
"defu": "^6.1.2",
5656
"kirby-types": "^0.6.2",
5757
"ofetch": "^1.3.3",

pnpm-lock.yaml

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/runtime/composables/useKirbyData.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { joinURL } from 'ufo'
33
import { hash } from 'ohash'
44
import type { FetchError } from 'ofetch'
55
import type { NitroFetchOptions } from 'nitropack'
6+
import type { WatchSource } from 'vue'
67
import type { AsyncData, AsyncDataOptions } from 'nuxt/app'
78
import { toValue } from '@vueuse/core'
89
import type { MaybeRefOrGetter } from '@vueuse/core'
910
import { DEFAULT_CLIENT_ERROR, getAuthHeader, getProxyPath, headersToObject } from '../utils'
1011
import { useAsyncData, useRuntimeConfig } from '#imports'
1112

12-
type UseKirbyDataOptions<T> = AsyncDataOptions<T> & Pick<
13+
type UseKirbyDataOptions<T> = Omit<AsyncDataOptions<T>, 'watch'> & Pick<
1314
NitroFetchOptions<string>,
1415
| 'onRequest'
1516
| 'onRequestError'
@@ -26,7 +27,7 @@ type UseKirbyDataOptions<T> = AsyncDataOptions<T> & Pick<
2627
/**
2728
* Language code to fetch data for in multi-language Kirby setups.
2829
*/
29-
language?: string
30+
language?: MaybeRefOrGetter<string>
3031
/**
3132
* Skip the Nuxt server proxy and fetch directly from the API.
3233
* Requires `client` to be enabled in the module options as well.
@@ -38,6 +39,12 @@ type UseKirbyDataOptions<T> = AsyncDataOptions<T> & Pick<
3839
* @default true
3940
*/
4041
cache?: boolean
42+
/**
43+
* Watch an array of reactive sources and auto-refresh the fetch result when they change.
44+
* Path and language are watched by default. You can completely ignore reactive sources by using `watch: false`.
45+
* @default undefined
46+
*/
47+
watch?: (WatchSource<unknown> | object)[] | false
4148
}
4249

4350
export function useKirbyData<T = any>(
@@ -65,27 +72,28 @@ export function useKirbyData<T = any>(
6572
const { kql } = useRuntimeConfig().public
6673
const _path = computed(() => {
6774
const value = toValue(path).replace(/^\//, '')
68-
return language ? joinURL(language, value) : value
75+
return language ? joinURL(toValue(language), value) : value
6976
})
77+
const _language = computed(() => toValue(language))
7078

71-
if (!_path.value || (language && !_path.value.replace(new RegExp(`^${language}/`), '')))
79+
if (!_path.value || (_language.value && !_path.value.replace(new RegExp(`^${_language.value}/`), '')))
7280
console.warn('[useKirbyData] Empty Kirby path')
7381

7482
if (client && !kql.client)
7583
throw new Error(DEFAULT_CLIENT_ERROR)
7684

77-
const baseHeaders = headersToObject(headers)
78-
7985
const asyncDataOptions: AsyncDataOptions<T> = {
8086
server,
8187
lazy,
8288
default: defaultFn,
8389
transform,
8490
pick,
85-
watch: [
86-
_path,
87-
...(watch || []),
88-
],
91+
watch: watch === false
92+
? []
93+
: [
94+
_path,
95+
...(watch || []),
96+
],
8997
immediate,
9098
}
9199

@@ -94,7 +102,7 @@ export function useKirbyData<T = any>(
94102
body: {
95103
path: _path,
96104
query,
97-
headers: Object.keys(baseHeaders).length ? baseHeaders : undefined,
105+
headers: headersToObject(headers),
98106
method,
99107
body,
100108
cache,
@@ -105,7 +113,7 @@ export function useKirbyData<T = any>(
105113
baseURL: kql.url,
106114
query,
107115
headers: {
108-
...baseHeaders,
116+
...headersToObject(headers),
109117
...getAuthHeader(kql),
110118
},
111119
method,
@@ -117,8 +125,6 @@ export function useKirbyData<T = any>(
117125
_path.value,
118126
query,
119127
method,
120-
body,
121-
language,
122128
])}`)
123129

124130
return useAsyncData<T, FetchError>(

src/runtime/composables/useKql.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import { computed, reactive } from 'vue'
22
import { hash } from 'ohash'
33
import type { FetchError } from 'ofetch'
44
import type { NitroFetchOptions } from 'nitropack'
5+
import type { WatchSource } from 'vue'
56
import type { AsyncData, AsyncDataOptions } from 'nuxt/app'
67
import type { KirbyQueryRequest, KirbyQueryResponse } from 'kirby-types'
78
import { toValue } from '@vueuse/core'
89
import type { MaybeRefOrGetter } from '@vueuse/core'
910
import { DEFAULT_CLIENT_ERROR, getAuthHeader, getProxyPath, headersToObject } from '../utils'
1011
import { useAsyncData, useRuntimeConfig } from '#imports'
1112

12-
export type UseKqlOptions<T> = AsyncDataOptions<T> & Pick<
13+
export type UseKqlOptions<T> = Omit<AsyncDataOptions<T>, 'watch'> & Pick<
1314
NitroFetchOptions<string>,
1415
| 'onRequest'
1516
| 'onRequestError'
@@ -23,7 +24,7 @@ export type UseKqlOptions<T> = AsyncDataOptions<T> & Pick<
2324
/**
2425
* Language code to fetch data for in multi-language Kirby setups.
2526
*/
26-
language?: string
27+
language?: MaybeRefOrGetter<string>
2728
/**
2829
* Skip the Nuxt server proxy and fetch directly from the API.
2930
* Requires `client` to be enabled in the module options as well.
@@ -35,6 +36,12 @@ export type UseKqlOptions<T> = AsyncDataOptions<T> & Pick<
3536
* @default true
3637
*/
3738
cache?: boolean
39+
/**
40+
* Watch an array of reactive sources and auto-refresh the fetch result when they change.
41+
* Query and language are watched by default. You can completely ignore reactive sources by using `watch: false`.
42+
* @default undefined
43+
*/
44+
watch?: (WatchSource<unknown> | object)[] | false
3845
}
3946

4047
export function useKql<
@@ -58,6 +65,7 @@ export function useKql<
5865

5966
const { kql } = useRuntimeConfig().public
6067
const _query = computed(() => toValue(query))
68+
const _language = computed(() => toValue(language))
6169

6270
if (Object.keys(_query.value).length === 0 || !_query.value.query)
6371
console.error('[useKql] Empty KQL query')
@@ -71,39 +79,42 @@ export function useKql<
7179
default: defaultFn,
7280
transform,
7381
pick,
74-
watch: [
75-
_query,
76-
...(watch || []),
77-
],
82+
watch: watch === false
83+
? []
84+
: [
85+
_query,
86+
_language,
87+
...(watch || []),
88+
],
7889
immediate,
7990
}
8091

81-
const baseHeaders = {
82-
...headersToObject(headers),
83-
...(language && { 'X-Language': language }),
84-
}
85-
8692
const _serverFetchOptions = reactive<NitroFetchOptions<string>>({
8793
method: 'POST',
8894
body: {
8995
query: _query,
9096
cache,
91-
headers: Object.keys(baseHeaders).length ? baseHeaders : undefined,
97+
headers: computed(() => ({
98+
...headersToObject(headers),
99+
...(_language.value && { 'X-Language': _language.value }),
100+
})),
92101
},
93102
})
94103

95104
const _clientFetchOptions = reactive<NitroFetchOptions<string>>({
96105
baseURL: kql.url,
97106
method: 'POST',
98107
body: _query,
99-
headers: {
100-
...baseHeaders,
108+
// @ts-expect-error: Reactive value
109+
headers: computed(() => ({
110+
...headersToObject(headers),
111+
...(_language.value && { 'X-Language': _language.value }),
101112
...getAuthHeader(kql),
102-
},
113+
})),
103114
})
104115

105116
let controller: AbortController | undefined
106-
const key = computed(() => `$kql${hash([_query.value, language])}`)
117+
const key = computed(() => `$kql${hash([_query.value, _language.value])}`)
107118

108119
return useAsyncData<ResT, FetchError>(
109120
key.value,

src/runtime/utils.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ export function getProxyPath(key: string) {
77
}
88

99
export function headersToObject(headers: HeadersInit = {}): Record<string, string> {
10-
if (headers instanceof Headers)
11-
return Object.fromEntries([...headers.entries()])
12-
13-
if (Array.isArray(headers))
10+
if (headers instanceof Headers || Array.isArray(headers))
1411
return Object.fromEntries(headers)
1512

1613
return headers

0 commit comments

Comments
 (0)