mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-21 21:25:11 +00:00
feat(nuxt): allow readonly option for useCookie
(#24503)
This commit is contained in:
parent
0c47399f33
commit
e3b8b84a24
@ -133,6 +133,10 @@ be returned as the cookie's value.
|
||||
|
||||
Specifies a function that returns the cookie's default value. The function can also return a `Ref`.
|
||||
|
||||
### `readonly`
|
||||
|
||||
Allows _accessing_ a cookie value without the ability to set it.
|
||||
|
||||
### `watch`
|
||||
|
||||
Specifies the `boolean` or `string` value for [watch](https://vuejs.org/api/reactivity-core.html#watch) cookie ref data.
|
||||
|
@ -16,6 +16,7 @@ export interface CookieOptions<T = any> extends _CookieOptions {
|
||||
encode?(value: T): string
|
||||
default?: () => T | Ref<T>
|
||||
watch?: boolean | 'shallow'
|
||||
readonly?: boolean
|
||||
}
|
||||
|
||||
export interface CookieRef<T> extends Ref<T> {}
|
||||
@ -27,6 +28,8 @@ const CookieDefaults = {
|
||||
encode: val => encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val))
|
||||
} satisfies CookieOptions<any>
|
||||
|
||||
export function useCookie<T = string | null | undefined> (name: string, _opts?: CookieOptions<T> & { readonly?: false }): CookieRef<T>
|
||||
export function useCookie<T = string | null | undefined> (name: string, _opts: CookieOptions<T> & { readonly: true }): Readonly<CookieRef<T>>
|
||||
export function useCookie<T = string | null | undefined> (name: string, _opts?: CookieOptions<T>): CookieRef<T> {
|
||||
const opts = { ...CookieDefaults, ..._opts }
|
||||
const cookies = readRawCookies(opts) || {}
|
||||
@ -55,6 +58,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
||||
if (import.meta.client) {
|
||||
const channel = typeof BroadcastChannel === 'undefined' ? null : new BroadcastChannel(`nuxt:cookies:${name}`)
|
||||
const callback = () => {
|
||||
if (opts.readonly || isEqual(cookie.value, cookies[name])) { return }
|
||||
writeClientCookie(name, cookie.value, opts as CookieSerializeOptions)
|
||||
channel?.postMessage(opts.encode(cookie.value as T))
|
||||
}
|
||||
@ -72,7 +76,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
||||
if (channel) {
|
||||
channel.onmessage = (event) => {
|
||||
watchPaused = true
|
||||
cookie.value = opts.decode(event.data)
|
||||
cookies[name] = cookie.value = opts.decode(event.data)
|
||||
nextTick(() => { watchPaused = false })
|
||||
}
|
||||
}
|
||||
@ -89,9 +93,8 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
||||
} else if (import.meta.server) {
|
||||
const nuxtApp = useNuxtApp()
|
||||
const writeFinalCookieValue = () => {
|
||||
if (!isEqual(cookie.value, cookies[name])) {
|
||||
writeServerCookie(useRequestEvent(nuxtApp), name, cookie.value, opts as CookieOptions<any>)
|
||||
}
|
||||
if (opts.readonly || isEqual(cookie.value, cookies[name])) { return }
|
||||
writeServerCookie(useRequestEvent(nuxtApp), name, cookie.value, opts as CookieOptions<any>)
|
||||
}
|
||||
const unhook = nuxtApp.hooks.hookOnce('app:rendered', writeFinalCookieValue)
|
||||
nuxtApp.hooks.hookOnce('app:error', () => {
|
||||
|
5
test/fixtures/basic-types/types.ts
vendored
5
test/fixtures/basic-types/types.ts
vendored
@ -346,6 +346,11 @@ describe('composables', () => {
|
||||
expectTypeOf(useFetch('/test', { default: () => 500 }).data).toEqualTypeOf<Ref<unknown>>()
|
||||
})
|
||||
|
||||
it('enforces readonly cookies', () => {
|
||||
// @ts-expect-error readonly cookie
|
||||
useCookie('test', { readonly: true }).value = 'thing'
|
||||
})
|
||||
|
||||
it('correct types when using ResT type-assertion with default function', () => {
|
||||
// @ts-expect-error default type should match generic type
|
||||
useFetch<string>('/test', { default: () => 0 })
|
||||
|
Loading…
Reference in New Issue
Block a user