feat(nuxt): support async transforms for data composables (#26154)

This commit is contained in:
Daniel Roe 2024-03-08 19:22:46 +00:00 committed by GitHub
parent 4023f7c824
commit 0cc7f298f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 15 additions and 5 deletions

View File

@ -119,7 +119,7 @@ type AsyncDataOptions<DataT> = {
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT | Ref<DataT> | null
transform?: (input: DataT) => DataT
transform?: (input: DataT) => DataT | Promise<DataT>
pick?: string[]
watch?: WatchSource[]
getCachedData?: (key: string) => DataT

View File

@ -148,7 +148,7 @@ type UseFetchOptions<DataT> = {
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT
transform?: (input: DataT) => DataT
transform?: (input: DataT) => DataT | Promise<DataT>
pick?: string[]
watch?: WatchSource[] | false
}

View File

@ -12,7 +12,7 @@ import { asyncDataDefaults } from '#build/nuxt.config.mjs'
export type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
export type _Transform<Input = any, Output = any> = (input: Input) => Output
export type _Transform<Input = any, Output = any> = (input: Input) => Output | Promise<Output>
export type PickFrom<T, K extends Array<string>> = T extends Array<any>
? T
@ -283,13 +283,13 @@ export function useAsyncData<
reject(err)
}
})
.then((_result) => {
.then(async (_result) => {
// If this request is cancelled, resolve to the latest request.
if ((promise as any).cancelled) { return nuxtApp._asyncDataPromises[key] }
let result = _result as unknown as DataT
if (options.transform) {
result = options.transform(_result)
result = await options.transform(_result)
}
if (options.pick) {
result = pick(result as any, options.pick) as DataT

View File

@ -418,6 +418,16 @@ describe('composables', () => {
expectTypeOf(useLazyAsyncData<string>(() => $fetch('/test'), { default: () => 'test', transform: () => 'transformed' }).data).toEqualTypeOf<Ref<string>>()
})
it('supports asynchronous transform', () => {
const { data } = useAsyncData('test', () => $fetch('/test') as Promise<{ foo: 'bar' }>, {
async transform (data) {
await Promise.resolve()
return data.foo
}
})
expectTypeOf(data).toEqualTypeOf<Ref<'bar' | null>>()
})
it('infer request url string literal from server/api routes', () => {
// request can accept dynamic string type
const dynamicStringUrl = 'https://example.com/api'