From 6aef45cc506cd4f543b356113820ed3ce4d27183 Mon Sep 17 00:00:00 2001 From: guen Date: Wed, 29 Oct 2025 02:07:14 +0700 Subject: [PATCH 1/5] fix(core): support reactive GraphQL documents in `useQuery` --- packages/core/src/composables/useQuery.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/core/src/composables/useQuery.ts b/packages/core/src/composables/useQuery.ts index ce256bf..05a24b7 100644 --- a/packages/core/src/composables/useQuery.ts +++ b/packages/core/src/composables/useQuery.ts @@ -119,7 +119,7 @@ export type UseQueryOptions( - document: DocumentNode | TypedDocumentNode, + document: MaybeRefOrGetter>, variables?: MaybeRefOrGetter, options?: UseQueryOptions ) { @@ -171,6 +171,8 @@ export function useQuery toValue(document)) + const getQueryOptions = () => { if (!options) { return {} @@ -189,7 +191,7 @@ export function useQuery({ ...getQueryOptions(), - query: document, + query: reactiveDocument.value, variables: toValue(reactiveVariables) }) @@ -271,7 +273,7 @@ export function useQuery({ - query: document, + query: reactiveDocument.value, variables: toValue(reactiveVariables) }) @@ -288,7 +290,7 @@ export function useQuery({ notifyOnNetworkStatusChange: options?.notifyOnNetworkStatusChange ?? options?.keepPreviousResult, - query: document, + query: reactiveDocument.value, variables: toValue(reactiveVariables), ...getQueryOptions() }) @@ -329,6 +331,16 @@ export function useQuery { + if (enabled.value) { + stop() + start() + } + }, { + deep: true, + flush: 'post' + }) } const refetch = async (variables?: TVariables) => { From 7dd73fa004afe23654f378837e7fe2e824c74a0b Mon Sep 17 00:00:00 2001 From: guen Date: Wed, 29 Oct 2025 02:47:20 +0700 Subject: [PATCH 2/5] feat(core): add support for `Todos` query with reactive GraphQL documents and UI integration --- packages/operations/src/codegen/gql.ts | 6 +- packages/operations/src/codegen/graphql.ts | 11 +++- .../operations/src/entries/queries.graphql | 6 ++ packages/web/src/App.vue | 61 +++++++++++++++++-- 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/packages/operations/src/codegen/gql.ts b/packages/operations/src/codegen/gql.ts index eb035f1..bcf379a 100644 --- a/packages/operations/src/codegen/gql.ts +++ b/packages/operations/src/codegen/gql.ts @@ -16,12 +16,12 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- type Documents = { "fragment PostDetail on Post {\n id\n title\n body\n}": typeof types.PostDetailFragmentDoc, "mutation UpdatePost($postId: Int!, $post: UpdatePostInput!) {\n updatePost(postId: $postId, post: $post) {\n id\n title\n }\n}": typeof types.UpdatePostDocument, - "query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}": typeof types.UserByIdDocument, + "query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}\n\nquery Todos($userId: Int, $first: Int) {\n todos(userId: $userId, first: $first) {\n id\n }\n}": typeof types.UserByIdDocument, }; const documents: Documents = { "fragment PostDetail on Post {\n id\n title\n body\n}": types.PostDetailFragmentDoc, "mutation UpdatePost($postId: Int!, $post: UpdatePostInput!) {\n updatePost(postId: $postId, post: $post) {\n id\n title\n }\n}": types.UpdatePostDocument, - "query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}": types.UserByIdDocument, + "query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}\n\nquery Todos($userId: Int, $first: Int) {\n todos(userId: $userId, first: $first) {\n id\n }\n}": types.UserByIdDocument, }; /** @@ -49,7 +49,7 @@ export function graphql(source: "mutation UpdatePost($postId: Int!, $post: Updat /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}"): (typeof documents)["query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}"]; +export function graphql(source: "query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}\n\nquery Todos($userId: Int, $first: Int) {\n todos(userId: $userId, first: $first) {\n id\n }\n}"): (typeof documents)["query UserById($userByIdId: Int!) {\n userById(id: $userByIdId) {\n id\n name\n email\n }\n}\n\nquery Posts($userId: Int, $first: Int) {\n posts(userId: $userId, first: $first) {\n id\n ...PostDetail\n }\n}\n\nquery Todos($userId: Int, $first: Int) {\n todos(userId: $userId, first: $first) {\n id\n }\n}"]; export function graphql(source: string) { return (documents as any)[source] ?? {}; diff --git a/packages/operations/src/codegen/graphql.ts b/packages/operations/src/codegen/graphql.ts index 4a096f6..36307d3 100644 --- a/packages/operations/src/codegen/graphql.ts +++ b/packages/operations/src/codegen/graphql.ts @@ -241,7 +241,16 @@ export type PostsQuery = { __typename?: 'Query', posts?: Array<( & { ' $fragmentRefs'?: { 'PostDetailFragment': PostDetailFragment } } ) | null> | null }; +export type TodosQueryVariables = Exact<{ + userId?: InputMaybe; + first?: InputMaybe; +}>; + + +export type TodosQuery = { __typename?: 'Query', todos?: Array<{ __typename?: 'Todo', id: number } | null> | null }; + export const PostDetailFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PostDetail"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Post"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"body"}}]}}]} as unknown as DocumentNode; export const UpdatePostDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdatePost"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"postId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"post"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdatePostInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updatePost"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"postId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"postId"}}},{"kind":"Argument","name":{"kind":"Name","value":"post"},"value":{"kind":"Variable","name":{"kind":"Name","value":"post"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}}]}}]}}]} as unknown as DocumentNode; export const UserByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userByIdId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userById"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userByIdId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}}]}}]} as unknown as DocumentNode; -export const PostsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Posts"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"posts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userId"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"PostDetail"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PostDetail"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Post"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"body"}}]}}]} as unknown as DocumentNode; \ No newline at end of file +export const PostsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Posts"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"posts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userId"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"PostDetail"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PostDetail"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Post"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"body"}}]}}]} as unknown as DocumentNode; +export const TodosDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Todos"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"todos"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userId"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/packages/operations/src/entries/queries.graphql b/packages/operations/src/entries/queries.graphql index 43ce851..c48f3b4 100644 --- a/packages/operations/src/entries/queries.graphql +++ b/packages/operations/src/entries/queries.graphql @@ -11,4 +11,10 @@ query Posts($userId: Int, $first: Int) { id ...PostDetail } +} + +query Todos($userId: Int, $first: Int) { + todos(userId: $userId, first: $first) { + id + } } \ No newline at end of file diff --git a/packages/web/src/App.vue b/packages/web/src/App.vue index f978681..941d1aa 100644 --- a/packages/web/src/App.vue +++ b/packages/web/src/App.vue @@ -1,9 +1,14 @@