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..b09bf7853e --- /dev/null +++ b/integrations/react-next-15/app/authors/page.tsx @@ -0,0 +1,16 @@ +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..b286611feb 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,29 @@ 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)}
+
+ ) +} diff --git a/integrations/react-next-15/app/page.tsx b/integrations/react-next-15/app/page.tsx index 6752ff7375..cbc156dac9 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,21 @@ 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..f3f142e9a0 --- /dev/null +++ b/integrations/react-next-15/app/query.ts @@ -0,0 +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< + 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 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< + 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< + 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), + }) +} 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':