Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
de920b4
update
matthewhausman Oct 18, 2022
381b422
Update utils.ts
matthewhausman Oct 18, 2022
a7f9195
Update types.ts
matthewhausman Oct 18, 2022
20a3ba9
potentail fix to parseArgs typing
matthewhausman Oct 18, 2022
cf78d2f
change name of maybeRefArgs
matthewhausman Oct 18, 2022
af9d5a2
Update useMutation.ts
matthewhausman Oct 18, 2022
927f5f3
update
matthewhausman Oct 18, 2022
b5ec820
revert some stuff
matthewhausman Oct 18, 2022
f4d0ebf
Update types.ts
matthewhausman Oct 18, 2022
972af36
Update types.ts
matthewhausman Oct 18, 2022
046452b
update
matthewhausman Oct 18, 2022
17731e1
Update types.ts
matthewhausman Oct 18, 2022
cc669dd
Update types.ts
matthewhausman Oct 18, 2022
918755f
Update useMutation.ts
matthewhausman Oct 19, 2022
e826d02
update
matthewhausman Oct 19, 2022
c390809
update
matthewhausman Oct 19, 2022
5079492
Update useMutation.ts
matthewhausman Oct 19, 2022
857e2ce
Update useMutation.ts
matthewhausman Oct 19, 2022
6a9035b
PR feedback
matthewhausman Oct 19, 2022
7118264
Update useMutation.ts
matthewhausman Oct 19, 2022
95864b2
Update types.ts
matthewhausman Oct 19, 2022
0a06a18
Update useMutation.ts
matthewhausman Oct 19, 2022
097de89
Update types.ts
matthewhausman Oct 19, 2022
a4ccbc4
Update types.ts
matthewhausman Oct 19, 2022
4976e2e
Update useMutation.ts
matthewhausman Oct 19, 2022
ccf20b2
Update types.ts
matthewhausman Oct 20, 2022
98904f8
Update useMutation.ts
matthewhausman Oct 20, 2022
41be28a
update
matthewhausman Oct 20, 2022
8a19aa1
update fn names
matthewhausman Oct 20, 2022
e5fee68
change subscribe to const
matthewhausman Oct 20, 2022
3c88803
Update types.ts
matthewhausman Oct 21, 2022
34ced5c
Update useMutation.ts
matthewhausman Oct 21, 2022
fab0f73
wrong arg passed in useMutation, unnecessary changes in testing files…
matthewhausman Oct 22, 2022
e6b1641
update
matthewhausman Oct 22, 2022
fab13aa
update
matthewhausman Oct 22, 2022
7f96936
Update useMutation.test.ts
matthewhausman Oct 22, 2022
412ab66
Update useMutation.test.ts
matthewhausman Oct 22, 2022
f879965
update
matthewhausman Oct 22, 2022
9684698
Update useMutation.test.ts
matthewhausman Oct 22, 2022
830ecfc
Update useMutation.test.ts
matthewhausman Oct 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"watch": "concurrently --kill-others \"rollup --config rollup.config.js -w\" \"pnpm run typecheck --watch\"",
"dev": "pnpm run watch",
"prettier": "prettier \"packages/*/{src/**,examples/**/src/**}.{md,js,jsx,ts,tsx,json}\"",
"prettier:write": "pnpm run prettier -- --write",
"prettier:write": "pnpm run prettier --write",
"cipublish": "ts-node scripts/publish.ts"
},
"namespace": "@tanstack",
Expand Down
51 changes: 45 additions & 6 deletions packages/vue-query/src/__tests__/useMutation.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { reactive } from 'vue-demi'
import { reactive, ref } from 'vue-demi'
import { errorMutator, flushPromises, successMutator } from './test-utils'
import { parseMutationArgs, useMutation } from '../useMutation'
import { useQueryClient } from '../useQueryClient'
Expand Down Expand Up @@ -35,11 +35,8 @@ describe('useMutation', () => {

test('should return error when request fails', async () => {
const mutation = useMutation(errorMutator)

mutation.mutate()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think changes in this file are relevant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok will take another look - for some reason or another passing no args was failing the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen Shot 2022-10-22 at 4 33 44 PM

Any idea why these changes would cause something as such?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no idea.
Does it work on main branch?
What TS version do you have installed?

Copy link
Contributor Author

@matthewhausman matthewhausman Oct 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that test is running on your cloud test suite - not my local so not sure if my ts version is relevant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export type MutateFunction<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown,

= (
variables: TVariables,
options?: MutateOptions<TData, TError, TVariables, TContext>,
) => Promise

it seems completely reasonable to get an error for not passing args - variables is not optional. Maybe I somehow removed a Partial somewhere... pretty strange


mutation.mutate({})
await flushPromises(10)

expect(mutation).toMatchObject({
isIdle: { value: false },
isLoading: { value: false },
Expand Down Expand Up @@ -88,6 +85,48 @@ describe('useMutation', () => {
expect(mutations?.options.mutationKey).toEqual(['bar'])
})

test('should update reactive options deeply', async () => {
type MutationKeyTest = {
entity: string
otherObject: {
name: string
someFn: Function
}
}
const mutationKey = ref<MutationKeyTest[]>([
{
entity: 'test',
otherObject: { name: 'objectName', someFn: () => null },
},
])
const queryClient = useQueryClient()
const mutationCache = queryClient.getMutationCache()
const options = reactive({ mutationKey })
const mutation = useMutation(
(params: string) => successMutator(params),
options,
)

mutationKey.value[0]!.otherObject.name = 'someOtherObjectName'
await flushPromises()
mutation.mutate('xyz')

await flushPromises()

const mutations = mutationCache.getAll()
const relevantMutation = mutations.find((m) => {
return (
Array.isArray(m.options.mutationKey) &&
!!m.options.mutationKey[0].otherObject
)
})

expect(
(relevantMutation?.options.mutationKey as MutationKeyTest[])[0]
?.otherObject.name === 'someOtherObjectName',
)
})

test('should reset state after invoking mutation.reset', async () => {
const mutation = useMutation((params: string) => errorMutator(params))

Expand Down Expand Up @@ -237,7 +276,7 @@ describe('useMutation', () => {
test('should throw on error', async () => {
const mutation = useMutation(errorMutator)

await expect(mutation.mutateAsync()).rejects.toThrowError('Some error')
await expect(mutation.mutateAsync({})).rejects.toThrowError('Some error')

expect(mutation).toMatchObject({
isIdle: { value: false },
Expand Down
17 changes: 8 additions & 9 deletions packages/vue-query/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import type { Ref, UnwrapRef } from 'vue-demi'
import type { QueryClient } from './queryClient'

export type MaybeRef<T> = Ref<T> | T
export type MaybeRefDeep<T> = T extends Function
? T
: MaybeRef<
T extends object
? {
[Property in keyof T]: MaybeRefDeep<T[Property]>
}
: T
>

export type MaybeRefDeep<T> = MaybeRef<
T extends object
? {
[Property in keyof T]: MaybeRefDeep<T[Property]>
}
: T
>

export type WithQueryClientKey<T> = T & {
queryClientKey?: string
Expand Down
136 changes: 89 additions & 47 deletions packages/vue-query/src/useMutation.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import { onScopeDispose, reactive, readonly, toRefs, watch } from 'vue-demi'
import {
onScopeDispose,
reactive,
readonly,
toRefs,
watch,
computed,
isRef,
} from 'vue-demi'
import type { ToRefs } from 'vue-demi'
import { MutationObserver } from '@tanstack/query-core'
import type {
MutateOptions,
MutationFunction,
MutationKey,
MutationObserverOptions,
MutateFunction,
MutationObserverResult,
MutationObserverOptions,
} from '@tanstack/query-core'
import { cloneDeepUnref, isQueryKey, updateState } from './utils'
import type { WithQueryClientKey, MaybeRef, MaybeRefDeep } from './types'
import { MutationObserver } from '@tanstack/query-core'
import { cloneDeepUnref, updateState, isMutationKey } from './utils'
import { useQueryClient } from './useQueryClient'
import type { WithQueryClientKey } from './types'

type MutationResult<TData, TError, TVariables, TContext> = Omit<
MutationObserverResult<TData, TError, TVariables, TContext>,
Expand All @@ -23,6 +31,22 @@ export type UseMutationOptions<TData, TError, TVariables, TContext> =
MutationObserverOptions<TData, TError, TVariables, TContext>
>

export type VueMutationObserverOptions<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown,
> = {
[Property in keyof UseMutationOptions<
TData,
TError,
TVariables,
TContext
>]: MaybeRefDeep<
UseMutationOptions<TData, TError, TVariables, TContext>[Property]
>
}

type MutateSyncFunction<
TData = unknown,
TError = unknown,
Expand Down Expand Up @@ -50,18 +74,22 @@ export function useMutation<
TVariables = void,
TContext = unknown,
>(
options: UseMutationOptions<TData, TError, TVariables, TContext>,
options: MaybeRef<
VueMutationObserverOptions<TData, TError, TVariables, TContext>
>,
): UseMutationReturnType<TData, TError, TVariables, TContext>
export function useMutation<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown,
>(
mutationFn: MutationFunction<TData, TVariables>,
options?: Omit<
UseMutationOptions<TData, TError, TVariables, TContext>,
'mutationFn'
mutationFn: MaybeRef<MutationFunction<TData, TVariables>>,
options?: MaybeRef<
Omit<
VueMutationObserverOptions<TData, TError, TVariables, TContext>,
'mutationFn'
>
>,
): UseMutationReturnType<TData, TError, TVariables, TContext>
export function useMutation<
Expand All @@ -70,10 +98,12 @@ export function useMutation<
TVariables = void,
TContext = unknown,
>(
mutationKey: MutationKey,
options?: Omit<
UseMutationOptions<TData, TError, TVariables, TContext>,
'mutationKey'
mutationKey: MaybeRef<MutationKey>,
options?: MaybeRef<
Omit<
VueMutationObserverOptions<TData, TError, TVariables, TContext>,
'mutationKey'
>
>,
): UseMutationReturnType<TData, TError, TVariables, TContext>
export function useMutation<
Expand All @@ -82,11 +112,13 @@ export function useMutation<
TVariables = void,
TContext = unknown,
>(
mutationKey: MutationKey,
mutationFn?: MutationFunction<TData, TVariables>,
options?: Omit<
UseMutationOptions<TData, TError, TVariables, TContext>,
'mutationKey' | 'mutationFn'
mutationKey: MaybeRef<MutationKey>,
mutationFn?: MaybeRef<MutationFunction<TData, TVariables>>,
options?: MaybeRef<
Omit<
VueMutationObserverOptions<TData, TError, TVariables, TContext>,
'mutationKey' | 'mutationFn'
>
>,
): UseMutationReturnType<TData, TError, TVariables, TContext>
export function useMutation<
Expand All @@ -96,20 +128,25 @@ export function useMutation<
TContext = unknown,
>(
arg1:
| MutationKey
| MutationFunction<TData, TVariables>
| UseMutationOptions<TData, TError, TVariables, TContext>,
| MaybeRef<MutationKey>
| MaybeRef<MutationFunction<TData, TVariables>>
| MaybeRef<VueMutationObserverOptions<TData, TError, TVariables, TContext>>,
arg2?:
| MutationFunction<TData, TVariables>
| UseMutationOptions<TData, TError, TVariables, TContext>,
arg3?: UseMutationOptions<TData, TError, TVariables, TContext>,
| MaybeRef<MutationFunction<TData, TVariables>>
| MaybeRef<VueMutationObserverOptions<TData, TError, TVariables, TContext>>,
arg3?: MaybeRef<
VueMutationObserverOptions<TData, TError, TVariables, TContext>
>,
): UseMutationReturnType<TData, TError, TVariables, TContext> {
const options = parseMutationArgs(arg1, arg2, arg3)
const options = computed(() => {
return parseMutationArgs(arg1, arg2, arg3)
})
const queryClient =
options.queryClient ?? useQueryClient(options.queryClientKey)
const defaultedOptions = queryClient.defaultMutationOptions(options)
const observer = new MutationObserver(queryClient, defaultedOptions)

options.value.queryClient ?? useQueryClient(options.value.queryClientKey)
const observer = new MutationObserver(
queryClient,
queryClient.defaultMutationOptions(options.value),
)
const state = reactive(observer.getCurrentResult())

const unsubscribe = observer.subscribe((result) => {
Expand All @@ -126,11 +163,9 @@ export function useMutation<
}

watch(
[() => arg1, () => arg2, () => arg3],
options,
() => {
observer.setOptions(
queryClient.defaultMutationOptions(parseMutationArgs(arg1, arg2, arg3)),
)
observer.setOptions(queryClient.defaultMutationOptions(options.value))
},
{ deep: true },
)
Expand Down Expand Up @@ -158,26 +193,33 @@ export function parseMutationArgs<
TContext = unknown,
>(
arg1:
| MutationKey
| MutationFunction<TData, TVariables>
| UseMutationOptions<TData, TError, TVariables, TContext>,
| MaybeRef<MutationKey>
| MaybeRef<MutationFunction<TData, TVariables>>
| MaybeRef<VueMutationObserverOptions<TData, TError, TVariables, TContext>>,
arg2?:
| MutationFunction<TData, TVariables>
| UseMutationOptions<TData, TError, TVariables, TContext>,
arg3?: UseMutationOptions<TData, TError, TVariables, TContext>,
): UseMutationOptions<TData, TError, TVariables, TContext> {
| MaybeRef<MutationFunction<TData, TVariables>>
| MaybeRef<VueMutationObserverOptions<TData, TError, TVariables, TContext>>,
arg3?: MaybeRef<
VueMutationObserverOptions<TData, TError, TVariables, TContext>
>,
): WithQueryClientKey<
MutationObserverOptions<TData, TError, TVariables, TContext>
> {
let options = arg1

if (isQueryKey(arg1)) {
if (typeof arg2 === 'function') {
options = { ...arg3, mutationKey: arg1, mutationFn: arg2 }
if (isMutationKey(arg1)) {
const plainFn = isRef(arg2) ? arg2.value : arg2
const plainOptions = isRef(arg3) ? arg3.value : arg3
if (typeof plainFn === 'function') {
options = { ...plainOptions, mutationKey: arg1, mutationFn: plainFn }
} else {
options = { ...arg2, mutationKey: arg1 }
}
}

if (typeof arg1 === 'function') {
options = { ...arg2, mutationFn: arg1 }
const plainFn = isRef(arg1) ? arg1.value : arg1
const plainOptions = isRef(arg2) ? arg2.value : arg2
if (typeof plainFn === 'function') {
options = { ...plainOptions, mutationFn: plainFn }
}

return cloneDeepUnref(options) as UseMutationOptions<
Expand Down
7 changes: 6 additions & 1 deletion packages/vue-query/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { QueryKey } from '@tanstack/query-core'
import type { QueryKey, MutationKey } from '@tanstack/query-core'
import { isRef, unref } from 'vue-demi'
import type { UnwrapRef } from 'vue-demi'
import type { MaybeRef } from './types'

export const VUE_QUERY_CLIENT = 'VUE_QUERY_CLIENT'

Expand All @@ -14,6 +15,10 @@ export function isQueryKey(value: unknown): value is QueryKey {
return Array.isArray(value)
}

export function isMutationKey(value: unknown): value is MaybeRef<MutationKey> {
return Array.isArray(isRef(value) ? value.value : value)
}

export function updateState(
state: Record<string, unknown>,
update: Record<string, any>,
Expand Down