From 083b7d07860e216f422799c02377f9ae57890619 Mon Sep 17 00:00:00 2001 From: juliusmarminge Date: Fri, 21 Feb 2025 16:18:24 +0100 Subject: [PATCH 1/2] attempt repro --- .../react-next-15/app/authors/page.tsx | 18 ++ .../react-next-15/app/client-component.tsx | 35 +++- integrations/react-next-15/app/page.tsx | 19 ++- integrations/react-next-15/app/query.ts | 157 ++++++++++++++++++ integrations/react-next-15/package.json | 1 + pnpm-lock.yaml | 8 + 6 files changed, 231 insertions(+), 7 deletions(-) create mode 100644 integrations/react-next-15/app/authors/page.tsx create mode 100644 integrations/react-next-15/app/query.ts diff --git a/integrations/react-next-15/app/authors/page.tsx b/integrations/react-next-15/app/authors/page.tsx new file mode 100644 index 0000000000..f61e99b4da --- /dev/null +++ b/integrations/react-next-15/app/authors/page.tsx @@ -0,0 +1,18 @@ + +import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; +import { makeQueryClient } from "../make-query-client"; +import { getApiV1AuthorsOptions } from "../query"; +import { Authors } from "../client-component"; + +export default async function Page() { + const queryClient = makeQueryClient() + + const data = await queryClient.fetchQuery({...getApiV1AuthorsOptions()}) + + + return ( + + + + ) +} diff --git a/integrations/react-next-15/app/client-component.tsx b/integrations/react-next-15/app/client-component.tsx index f795255ecb..dd0906b95d 100644 --- a/integrations/react-next-15/app/client-component.tsx +++ b/integrations/react-next-15/app/client-component.tsx @@ -1,8 +1,9 @@ 'use client' - +import { useQuery, useSuspenseQuery } from "@tanstack/react-query" +import Link from "next/link" import React from 'react' -import { useQuery } from '@tanstack/react-query' import { Temporal } from '@js-temporal/polyfill' +import { getApiV1ActivitiesOptions, getApiV1AuthorsOptions } from './query' export function ClientComponent() { const query = useQuery({ @@ -34,3 +35,33 @@ export function ClientComponent() { ) } + + + + + +export const Activities = () => { + const { data: activities } = useSuspenseQuery({ + ...getApiV1ActivitiesOptions(), + }) + + return ( +
+ Authors +
{JSON.stringify(activities, null, 2)}
+
+ ) +} + +export const Authors = () => { + const { data: authors } = useSuspenseQuery({ + ...getApiV1AuthorsOptions(), + }) + + return ( +
+ Activities +
{JSON.stringify(authors, null, 2)}
+
+ ) +} \ No newline at end of file diff --git a/integrations/react-next-15/app/page.tsx b/integrations/react-next-15/app/page.tsx index 6752ff7375..a75a94070e 100644 --- a/integrations/react-next-15/app/page.tsx +++ b/integrations/react-next-15/app/page.tsx @@ -1,10 +1,11 @@ import { headers } from 'next/headers' -import React from 'react' +import React, { Suspense } from 'react' import { HydrationBoundary, dehydrate } from '@tanstack/react-query' import { Temporal } from '@js-temporal/polyfill' -import { ClientComponent } from './client-component' +import { Activities, ClientComponent } from './client-component' import { makeQueryClient } from './make-query-client' import { queryExampleAction } from './_action' +import { getApiV1ActivitiesOptions } from './query' export default function Home() { const queryClient = makeQueryClient() @@ -26,16 +27,24 @@ export default function Home() { }, }) + + void queryClient.prefetchQuery({ ...getApiV1ActivitiesOptions() }) + + const state = dehydrate(queryClient) return (
+
+ +
+ Loading activities...}> + +
-
- -
+
) } diff --git a/integrations/react-next-15/app/query.ts b/integrations/react-next-15/app/query.ts new file mode 100644 index 0000000000..53b54cbe75 --- /dev/null +++ b/integrations/react-next-15/app/query.ts @@ -0,0 +1,157 @@ +import { createClient, createConfig } from "@hey-api/client-next"; +import { queryOptions } from "@tanstack/react-query"; + +import type { Client, ClientOptions, CreateClientConfig, Options as HeyApiOptions, TDataShape } from "@hey-api/client-next"; + +export type Options = HeyApiOptions & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + + +export const createClientConfig: CreateClientConfig = (config) => ({ + ...config, + baseUrl: 'https://fakerestapi.azurewebsites.net/', +}) + + +export const _heyApiClient = createClient(createClientConfig(createConfig({ + baseUrl: 'https://fakerestapi.azurewebsites.net' +}))); + +export type GetApiV1ActivitiesData = { + body?: never; + path?: never; + query?: never; + url: '/api/v1/Activities'; +}; + +export type Activity = { + id?: number; + title?: string | null; + dueDate?: string; + completed?: boolean; +}; + +export type Author = { + id?: number; + idBook?: number; + firstName?: string | null; + lastName?: string | null; +}; + +export type GetApiV1ActivitiesResponses = { + /** + * Success + */ + 200: Array; +}; + +export type GetApiV1AuthorsData = { + body?: never; + path?: never; + query?: never; + url: '/api/v1/Authors'; +}; + +export type GetApiV1ActivitiesResponse = GetApiV1ActivitiesResponses[keyof GetApiV1ActivitiesResponses]; + +export type QueryKey = [ + Pick & { + _id: string; + _infinite?: boolean; + } +]; + + +const createQueryKey = (id: string, options?: TOptions, infinite?: boolean): [ + QueryKey[0] +] => { + const params: QueryKey[0] = { _id: id, baseUrl: (options?.client ?? _heyApiClient).getConfig().baseUrl } as QueryKey[0]; + if (infinite) { + params._infinite = infinite; + } + if (options?.body) { + params.body = options.body; + } + if (options?.headers) { + params.headers = options.headers; + } + if (options?.path) { + params.path = options.path; + } + if (options?.query) { + params.query = options.query; + } + return [ + params + ]; +}; + +export const getApiV1Activities = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + url: '/api/v1/Activities', + ...options + }); +}; + +export const getApiV1ActivitiesQueryKey = (options?: Options) => createQueryKey('getApiV1Activities', options); + + +export const getApiV1ActivitiesOptions = (options?: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getApiV1Activities({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getApiV1ActivitiesQueryKey(options) + }); +}; + +export type GetApiV1AuthorsResponses = { + /** + * Success + */ + 200: Array; +}; + +export type GetApiV1AuthorsResponse = GetApiV1AuthorsResponses[keyof GetApiV1AuthorsResponses]; + + +export const getApiV1Authors = (options?: Options) => { + return (options?.client ?? _heyApiClient).get({ + url: '/api/v1/Authors', + ...options + }); +}; + +export const getApiV1AuthorsQueryKey = (options?: Options) => createQueryKey('getApiV1Authors', options); + +export const getApiV1AuthorsOptions = (options?: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getApiV1Authors({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getApiV1AuthorsQueryKey(options) + }); +}; \ No newline at end of file diff --git a/integrations/react-next-15/package.json b/integrations/react-next-15/package.json index 19a3eeb774..2c666d1bd5 100644 --- a/integrations/react-next-15/package.json +++ b/integrations/react-next-15/package.json @@ -6,6 +6,7 @@ "build": "next build" }, "dependencies": { + "@hey-api/client-next": "^0.2.1", "@js-temporal/polyfill": "^0.4.4", "@tanstack/react-query": "workspace:*", "@tanstack/react-query-devtools": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eabf66e820..8efe63cfd0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1946,6 +1946,9 @@ importers: integrations/react-next-15: dependencies: + '@hey-api/client-next': + specifier: ^0.2.1 + version: 0.2.1 '@js-temporal/polyfill': specifier: ^0.4.4 version: 0.4.4 @@ -5010,6 +5013,9 @@ packages: peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@hey-api/client-next@0.2.1': + resolution: {integrity: sha512-/FJceHUYqvkbbLbloUhUbNwqrpaJXNfivYtlUFQVz58yqLH/BX1WW7IE+kIiPxWN8oPYaTPvbb2yIKagK3HmAg==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -19421,6 +19427,8 @@ snapshots: dependencies: graphql: 16.9.0 + '@hey-api/client-next@0.2.1': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': From ed672c5d223011398984d9a28cf66e269535fd00 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:20:18 +0000 Subject: [PATCH 2/2] ci: apply automated fixes --- .../react-next-15/app/authors/page.tsx | 14 +- .../react-next-15/app/client-component.tsx | 10 +- integrations/react-next-15/app/page.tsx | 3 - integrations/react-next-15/app/query.ts | 305 ++++++++++-------- 4 files changed, 178 insertions(+), 154 deletions(-) diff --git a/integrations/react-next-15/app/authors/page.tsx b/integrations/react-next-15/app/authors/page.tsx index f61e99b4da..b09bf7853e 100644 --- a/integrations/react-next-15/app/authors/page.tsx +++ b/integrations/react-next-15/app/authors/page.tsx @@ -1,14 +1,12 @@ - -import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; -import { makeQueryClient } from "../make-query-client"; -import { getApiV1AuthorsOptions } from "../query"; -import { Authors } from "../client-component"; +import { HydrationBoundary, dehydrate } from '@tanstack/react-query' +import { makeQueryClient } from '../make-query-client' +import { getApiV1AuthorsOptions } from '../query' +import { Authors } from '../client-component' export default async function Page() { - const queryClient = makeQueryClient() - - const data = await queryClient.fetchQuery({...getApiV1AuthorsOptions()}) + const queryClient = makeQueryClient() + const data = await queryClient.fetchQuery({ ...getApiV1AuthorsOptions() }) return ( diff --git a/integrations/react-next-15/app/client-component.tsx b/integrations/react-next-15/app/client-component.tsx index dd0906b95d..b286611feb 100644 --- a/integrations/react-next-15/app/client-component.tsx +++ b/integrations/react-next-15/app/client-component.tsx @@ -1,6 +1,6 @@ 'use client' -import { useQuery, useSuspenseQuery } from "@tanstack/react-query" -import Link from "next/link" +import { useQuery, useSuspenseQuery } from '@tanstack/react-query' +import Link from 'next/link' import React from 'react' import { Temporal } from '@js-temporal/polyfill' import { getApiV1ActivitiesOptions, getApiV1AuthorsOptions } from './query' @@ -36,10 +36,6 @@ export function ClientComponent() { ) } - - - - export const Activities = () => { const { data: activities } = useSuspenseQuery({ ...getApiV1ActivitiesOptions(), @@ -64,4 +60,4 @@ export const Authors = () => {
{JSON.stringify(authors, null, 2)}
) -} \ No newline at end of file +} diff --git a/integrations/react-next-15/app/page.tsx b/integrations/react-next-15/app/page.tsx index a75a94070e..cbc156dac9 100644 --- a/integrations/react-next-15/app/page.tsx +++ b/integrations/react-next-15/app/page.tsx @@ -27,10 +27,8 @@ export default function Home() { }, }) - void queryClient.prefetchQuery({ ...getApiV1ActivitiesOptions() }) - const state = dehydrate(queryClient) return ( @@ -44,7 +42,6 @@ export default function Home() {
- ) } diff --git a/integrations/react-next-15/app/query.ts b/integrations/react-next-15/app/query.ts index 53b54cbe75..f3f142e9a0 100644 --- a/integrations/react-next-15/app/query.ts +++ b/integrations/react-next-15/app/query.ts @@ -1,157 +1,190 @@ -import { createClient, createConfig } from "@hey-api/client-next"; -import { queryOptions } from "@tanstack/react-query"; - -import type { Client, ClientOptions, CreateClientConfig, Options as HeyApiOptions, TDataShape } from "@hey-api/client-next"; - -export type Options = HeyApiOptions & { - /** - * You can provide a client instance returned by `createClient()` instead of - * individual options. This might be also useful if you want to implement a - * custom client. - */ - client?: Client; - /** - * You can pass arbitrary values through the `meta` object. This can be - * used to access values that aren't defined as part of the SDK function. - */ - meta?: Record; -}; - +import { createClient, createConfig } from '@hey-api/client-next' +import { queryOptions } from '@tanstack/react-query' + +import type { + Client, + ClientOptions, + CreateClientConfig, + Options as HeyApiOptions, + TDataShape, +} from '@hey-api/client-next' + +export type Options< + TData extends TDataShape = TDataShape, + TThrowOnError extends boolean = boolean, +> = HeyApiOptions & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record +} export const createClientConfig: CreateClientConfig = (config) => ({ ...config, baseUrl: 'https://fakerestapi.azurewebsites.net/', }) - -export const _heyApiClient = createClient(createClientConfig(createConfig({ - baseUrl: 'https://fakerestapi.azurewebsites.net' -}))); +export const _heyApiClient = createClient( + createClientConfig( + createConfig({ + baseUrl: 'https://fakerestapi.azurewebsites.net', + }), + ), +) export type GetApiV1ActivitiesData = { - body?: never; - path?: never; - query?: never; - url: '/api/v1/Activities'; -}; + body?: never + path?: never + query?: never + url: '/api/v1/Activities' +} export type Activity = { - id?: number; - title?: string | null; - dueDate?: string; - completed?: boolean; -}; + id?: number + title?: string | null + dueDate?: string + completed?: boolean +} export type Author = { - id?: number; - idBook?: number; - firstName?: string | null; - lastName?: string | null; -}; + id?: number + idBook?: number + firstName?: string | null + lastName?: string | null +} export type GetApiV1ActivitiesResponses = { - /** - * Success - */ - 200: Array; -}; + /** + * Success + */ + 200: Array +} export type GetApiV1AuthorsData = { - body?: never; - path?: never; - query?: never; - url: '/api/v1/Authors'; -}; + body?: never + path?: never + query?: never + url: '/api/v1/Authors' +} -export type GetApiV1ActivitiesResponse = GetApiV1ActivitiesResponses[keyof GetApiV1ActivitiesResponses]; +export type GetApiV1ActivitiesResponse = + GetApiV1ActivitiesResponses[keyof GetApiV1ActivitiesResponses] export type QueryKey = [ - Pick & { - _id: string; - _infinite?: boolean; - } -]; - - -const createQueryKey = (id: string, options?: TOptions, infinite?: boolean): [ - QueryKey[0] -] => { - const params: QueryKey[0] = { _id: id, baseUrl: (options?.client ?? _heyApiClient).getConfig().baseUrl } as QueryKey[0]; - if (infinite) { - params._infinite = infinite; - } - if (options?.body) { - params.body = options.body; - } - if (options?.headers) { - params.headers = options.headers; - } - if (options?.path) { - params.path = options.path; - } - if (options?.query) { - params.query = options.query; - } - return [ - params - ]; -}; - -export const getApiV1Activities = (options?: Options) => { - return (options?.client ?? _heyApiClient).get({ - url: '/api/v1/Activities', - ...options - }); -}; - -export const getApiV1ActivitiesQueryKey = (options?: Options) => createQueryKey('getApiV1Activities', options); - - -export const getApiV1ActivitiesOptions = (options?: Options) => { - return queryOptions({ - queryFn: async ({ queryKey, signal }) => { - const { data } = await getApiV1Activities({ - ...options, - ...queryKey[0], - signal, - throwOnError: true - }); - return data; - }, - queryKey: getApiV1ActivitiesQueryKey(options) - }); -}; + Pick & { + _id: string + _infinite?: boolean + }, +] + +const createQueryKey = ( + id: string, + options?: TOptions, + infinite?: boolean, +): [QueryKey[0]] => { + const params: QueryKey[0] = { + _id: id, + baseUrl: (options?.client ?? _heyApiClient).getConfig().baseUrl, + } as QueryKey[0] + if (infinite) { + params._infinite = infinite + } + if (options?.body) { + params.body = options.body + } + if (options?.headers) { + params.headers = options.headers + } + if (options?.path) { + params.path = options.path + } + if (options?.query) { + params.query = options.query + } + return [params] +} + +export const getApiV1Activities = ( + options?: Options, +) => { + return (options?.client ?? _heyApiClient).get< + GetApiV1ActivitiesResponse, + unknown, + TThrowOnError + >({ + url: '/api/v1/Activities', + ...options, + }) +} + +export const getApiV1ActivitiesQueryKey = ( + options?: Options, +) => createQueryKey('getApiV1Activities', options) + +export const getApiV1ActivitiesOptions = ( + options?: Options, +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getApiV1Activities({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }) + return data + }, + queryKey: getApiV1ActivitiesQueryKey(options), + }) +} export type GetApiV1AuthorsResponses = { - /** - * Success - */ - 200: Array; -}; - -export type GetApiV1AuthorsResponse = GetApiV1AuthorsResponses[keyof GetApiV1AuthorsResponses]; - - -export const getApiV1Authors = (options?: Options) => { - return (options?.client ?? _heyApiClient).get({ - url: '/api/v1/Authors', - ...options - }); -}; - -export const getApiV1AuthorsQueryKey = (options?: Options) => createQueryKey('getApiV1Authors', options); - -export const getApiV1AuthorsOptions = (options?: Options) => { - return queryOptions({ - queryFn: async ({ queryKey, signal }) => { - const { data } = await getApiV1Authors({ - ...options, - ...queryKey[0], - signal, - throwOnError: true - }); - return data; - }, - queryKey: getApiV1AuthorsQueryKey(options) - }); -}; \ No newline at end of file + /** + * Success + */ + 200: Array +} + +export type GetApiV1AuthorsResponse = + GetApiV1AuthorsResponses[keyof GetApiV1AuthorsResponses] + +export const getApiV1Authors = ( + options?: Options, +) => { + return (options?.client ?? _heyApiClient).get< + GetApiV1AuthorsResponse, + unknown, + TThrowOnError + >({ + url: '/api/v1/Authors', + ...options, + }) +} + +export const getApiV1AuthorsQueryKey = ( + options?: Options, +) => createQueryKey('getApiV1Authors', options) + +export const getApiV1AuthorsOptions = ( + options?: Options, +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getApiV1Authors({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }) + return data + }, + queryKey: getApiV1AuthorsQueryKey(options), + }) +}