Skip to content

Commit

Permalink
fix(vue): fix variables typing (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
arkandias committed Jan 8, 2025
1 parent 25d114d commit e7f08e0
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 76 deletions.
4 changes: 2 additions & 2 deletions packages/vue-urql/src/useMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
} from '@urql/core';

import { useClient } from './useClient';
import type { MaybeRef } from './utils';
import type { MaybeRefOrGetter } from './utils';
import { createRequestWithArgs, useRequestState } from './utils';

/** State of the last mutation executed by {@link useMutation}.
Expand Down Expand Up @@ -132,7 +132,7 @@ export function useMutation<T = any, V extends AnyVariables = AnyVariables>(
}

export function callUseMutation<T = any, V extends AnyVariables = AnyVariables>(
query: MaybeRef<DocumentInput<T, V>>,
query: MaybeRefOrGetter<DocumentInput<T, V>>,
client: Ref<Client> = useClient()
): UseMutationResponse<T, V> {
const data: Ref<T | undefined> = shallowRef();
Expand Down
12 changes: 7 additions & 5 deletions packages/vue-urql/src/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {

import { useClient } from './useClient';

import type { MaybeRef, MaybeRefObj } from './utils';
import type { MaybeRefOrGetter, MaybeRefOrGetterObj } from './utils';
import { useRequestState, useClientState } from './utils';

/** Input arguments for the {@link useQuery} function.
Expand All @@ -42,7 +42,7 @@ export type UseQueryArgs<
*
* @see {@link OperationContext.requestPolicy} for where this value is set.
*/
requestPolicy?: MaybeRef<RequestPolicy>;
requestPolicy?: MaybeRefOrGetter<RequestPolicy>;
/** Updates the {@link OperationContext} for the executed GraphQL query operation.
*
* @remarks
Expand All @@ -60,7 +60,7 @@ export type UseQueryArgs<
* });
* ```
*/
context?: MaybeRef<Partial<OperationContext>>;
context?: MaybeRefOrGetter<Partial<OperationContext>>;
/** Prevents {@link useQuery} from automatically executing GraphQL query operations.
*
* @remarks
Expand All @@ -72,8 +72,10 @@ export type UseQueryArgs<
* @see {@link https://urql.dev/goto/docs/basics/vue#pausing-usequery} for
* documentation on the `pause` option.
*/
pause?: MaybeRef<boolean>;
} & MaybeRefObj<GraphQLRequestParams<Data, MaybeRefObj<Variables>>>;
pause?: MaybeRefOrGetter<boolean>;
} & MaybeRefOrGetterObj<
GraphQLRequestParams<Data, MaybeRefOrGetterObj<Variables>>
>;

/** State of the current query, your {@link useQuery} function is executing.
*
Expand Down
10 changes: 6 additions & 4 deletions packages/vue-urql/src/useSubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {

import { useClient } from './useClient';

import type { MaybeRef, MaybeRefObj } from './utils';
import type { MaybeRefOrGetter, MaybeRefOrGetterObj } from './utils';
import { useRequestState, useClientState } from './utils';

/** Input arguments for the {@link useSubscription} function.
Expand All @@ -36,7 +36,7 @@ export type UseSubscriptionArgs<
* {@link UseSubscriptionResponse.resume} is called, or, if `pause` is a reactive
* ref of a boolean, until this ref changes to `true`.
*/
pause?: MaybeRef<boolean>;
pause?: MaybeRefOrGetter<boolean>;
/** Updates the {@link OperationContext} for the executed GraphQL subscription operation.
*
* @remarks
Expand All @@ -54,8 +54,10 @@ export type UseSubscriptionArgs<
* });
* ```
*/
context?: MaybeRef<Partial<OperationContext>>;
} & MaybeRefObj<GraphQLRequestParams<Data, MaybeRefObj<Variables>>>;
context?: MaybeRefOrGetter<Partial<OperationContext>>;
} & MaybeRefOrGetterObj<
GraphQLRequestParams<Data, MaybeRefOrGetterObj<Variables>>
>;

/** Combines previous data with an incoming subscription result’s data.
*
Expand Down
103 changes: 38 additions & 65 deletions packages/vue-urql/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,43 @@ import type {
OperationResultSource,
} from '@urql/core';
import { createRequest } from '@urql/core';
import type { Ref } from 'vue';
import { type Ref, unref } from 'vue';
import { watchEffect, isReadonly, computed, ref, shallowRef, isRef } from 'vue';
import type { UseSubscriptionArgs } from './useSubscription';
import type { UseQueryArgs } from './useQuery';

export type MaybeRef<T> = T | (() => T) | Ref<T>;
export type MaybeRefObj<T> = T extends {}
? { [K in keyof T]: MaybeRef<T[K]> }
: T;

const unwrap = <T>(maybeRef: MaybeRef<T>): T =>
typeof maybeRef === 'function'
? (maybeRef as () => T)()
: maybeRef != null && isRef(maybeRef)
? maybeRef.value
: maybeRef;

const isPlainObject = (value: any): boolean => {
if (typeof value !== 'object' || value === null) return false;
return (
value.constructor &&
Object.getPrototypeOf(value).constructor === Object.prototype.constructor
);
};
export const isArray = Array.isArray;

const unwrapDeeply = <T>(input: T): T => {
input = isRef(input) ? (input.value as T) : input;

if (typeof input === 'function') {
return unwrapDeeply(input()) as T;
}

if (input && typeof input === 'object') {
if (isArray(input)) {
const length = input.length;
const out = new Array(length) as T;
let i = 0;
for (; i < length; i++) {
out[i] = unwrapDeeply(input[i]);
}

return out;
} else if (isPlainObject(input)) {
const keys = Object.keys(input);
const length = keys.length;
let i = 0;
let key: string;
const out = {} as T;

for (; i < length; i++) {
key = keys[i];
out[key] = unwrapDeeply(input[key]);
}

return out;
}
}

return input;
};
export type MaybeRefOrGetter<T> = T | (() => T) | Ref<T>;
export type MaybeRefOrGetterObj<T> =
| MaybeRefOrGetter<T>
| (T extends {} ? { [K in keyof T]: MaybeRefOrGetter<T[K]> } : T);

type UnwrapDeep<T> = T extends Ref<infer V> | (() => infer V)
? UnwrapDeep<V>
: T extends {}
? { [K in keyof T]: UnwrapDeep<T[K]> }
: T;

const isFunction = <T>(
val: MaybeRefOrGetter<T> | MaybeRefOrGetterObj<T>
): val is () => T => typeof val === 'function';
const isPlainObject = (val: unknown): val is object =>
typeof val === 'object' && val !== null && val.constructor === Object;

const toValue = <T>(source: MaybeRefOrGetter<T>): T =>
isFunction(source) ? source() : unref(source);

const toValueDeep = <T>(
source: MaybeRefOrGetter<T> | MaybeRefOrGetterObj<T>
): UnwrapDeep<T> =>
(isRef<T>(source) || isFunction<T>(source)
? toValueDeep(toValue(source))
: Array.isArray(source)
? source.map(val => toValueDeep(val))
: isPlainObject(source)
? Object.fromEntries(
Object.entries(source).map(([key, val]) => [key, toValueDeep(val)])
)
: source) as UnwrapDeep<T>;

export const createRequestWithArgs = <
T = any,
Expand All @@ -78,12 +54,9 @@ export const createRequestWithArgs = <
args:
| UseQueryArgs<T, V>
| UseSubscriptionArgs<T, V>
| { query: MaybeRef<DocumentInput<T, V>>; variables: V }
| { query: MaybeRefOrGetter<DocumentInput<T, V>>; variables: V }
) => {
return createRequest<T, V>(
unwrap(args.query),
unwrapDeeply(args.variables) as V
);
return createRequest<T, V>(toValue(args.query), toValueDeep(args.variables));

Check failure on line 59 in packages/vue-urql/src/utils.ts

View workflow job for this annotation

GitHub Actions / Checks

Property 'query' does not exist on type '({ requestPolicy?: MaybeRefOrGetter<RequestPolicy> | undefined; context?: MaybeRefOrGetter<Partial<OperationContext>> | undefined; pause?: MaybeRefOrGetter<...> | undefined; } & { ...; } & { ...; }) | ... 43 more ... | ({ ...; } & { ...; })'.

Check failure on line 59 in packages/vue-urql/src/utils.ts

View workflow job for this annotation

GitHub Actions / Checks

Property 'variables' does not exist on type '({ requestPolicy?: MaybeRefOrGetter<RequestPolicy> | undefined; context?: MaybeRefOrGetter<Partial<OperationContext>> | undefined; pause?: MaybeRefOrGetter<...> | undefined; } & { ...; } & { ...; }) | ... 43 more ... | ({ ...; } & { ...; })'.
};

export const useRequestState = <
Expand Down Expand Up @@ -125,11 +98,11 @@ export function useClientState<T = any, V extends AnyVariables = AnyVariables>(
const requestOptions = computed(() => {
return 'requestPolicy' in args
? {
requestPolicy: unwrap(args.requestPolicy),
...unwrap(args.context),
requestPolicy: toValue(args.requestPolicy),
...toValue(args.context),
}
: {
...unwrap(args.context),
...toValue(args.context),
};
});

Expand Down

0 comments on commit e7f08e0

Please # to comment.