diff --git a/.changepacks/changepack_log_TrNXrNzW_2CG0ILlaaUW3.json b/.changepacks/changepack_log_TrNXrNzW_2CG0ILlaaUW3.json new file mode 100644 index 0000000..2e5aa99 --- /dev/null +++ b/.changepacks/changepack_log_TrNXrNzW_2CG0ILlaaUW3.json @@ -0,0 +1 @@ +{"changes":{"packages/generator/package.json":"Patch"},"note":"Fix gen issue","date":"2025-12-04T13:14:14.424512200Z"} \ No newline at end of file diff --git a/.changepacks/changepack_log_c5-e3qOi7k21VRnLuw095.json b/.changepacks/changepack_log_c5-e3qOi7k21VRnLuw095.json new file mode 100644 index 0000000..5d538d7 --- /dev/null +++ b/.changepacks/changepack_log_c5-e3qOi7k21VRnLuw095.json @@ -0,0 +1 @@ +{"changes":{"packages/core/package.json":"Patch","packages/react-query/package.json":"Patch","packages/fetch/package.json":"Patch"},"note":"Fix query typing issue","date":"2025-12-04T13:14:26.431881700Z"} \ No newline at end of file diff --git a/bun.lock b/bun.lock index cfcc839..9168fb5 100644 --- a/bun.lock +++ b/bun.lock @@ -20,6 +20,7 @@ "dependencies": { "@devup-api/fetch": "workspace:*", "@devup-api/next-plugin": "workspace:*", + "@devup-api/react-query": "workspace:*", "@devup-ui/react": "^1", "next": "^16.0.4", "react": "^19.2.0", @@ -88,7 +89,7 @@ }, "packages/core": { "name": "@devup-api/core", - "version": "0.1.5", + "version": "0.1.6", "devDependencies": { "@types/node": "^24.10", "typescript": "^5.9", @@ -96,7 +97,7 @@ }, "packages/fetch": { "name": "@devup-api/fetch", - "version": "0.1.5", + "version": "0.1.7", "dependencies": { "@devup-api/core": "workspace:*", }, @@ -139,7 +140,7 @@ }, "packages/react-query": { "name": "@devup-api/react-query", - "version": "0.0.0", + "version": "0.1.0", "dependencies": { "@devup-api/fetch": "workspace:*", "@tanstack/react-query": ">=5.90", diff --git a/examples/next/app/page.tsx b/examples/next/app/page.tsx index b397ac1..05bfa8b 100644 --- a/examples/next/app/page.tsx +++ b/examples/next/app/page.tsx @@ -1,15 +1,46 @@ 'use client' import { createApi } from '@devup-api/fetch' +import { createQueryClient } from '@devup-api/react-query' import { Box, Text } from '@devup-ui/react' import { useEffect } from 'react' -const api = createApi('https://api.example.com') -const api2 = createApi('https://api.example2.com', undefined, 'openapi2.json') +const api = createApi({ + baseUrl: 'https://api.example.com', +}) +const api2 = createApi({ + baseUrl: 'https://api.example2.com', + serverName: 'openapi2.json', +}) + +const queryClient = createQueryClient(api) export default function Home() { + const { data, isLoading, error } = queryClient.useQuery('GET', 'getUsers', { + // params: { id: 1 }, + query: { + name: 'John Doe', + }, + }) + + console.info(data, isLoading, error) + + const { + data: data2, + error: error2, + mutateAsync, + } = queryClient.useMutation('GET', '/users/{id}', {}) + mutateAsync({ + params: { id: 1 }, + query: { + name: 'John Doe', + }, + }) + + console.info(data2, error2) + useEffect(() => { - api2.get('getUsers2', {}).then((res) => { + api2.get('getUsers2').then((res) => { console.log(res) }) api.get('getUsers', {}).then((res) => { diff --git a/examples/next/package.json b/examples/next/package.json index e0dd295..27e3dbe 100644 --- a/examples/next/package.json +++ b/examples/next/package.json @@ -14,6 +14,7 @@ "react-dom": "^19.2.0", "@devup-api/next-plugin": "workspace:*", "@devup-api/fetch": "workspace:*", + "@devup-api/react-query": "workspace:*", "@devup-ui/react": "^1" }, "devDependencies": { diff --git a/package.json b/package.json index 54d8514..acb11d7 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "lint": "biome check", "lint:fix": "biome check --write", "prepare": "husky", - "build": "bun run -F @devup-api/core build && bun run -F @devup-api/utils build && bun run -F @devup-api/generator build && bun run -F @devup-api/fetch build && bun run -F @devup-api/webpack-plugin build && bun run -F @devup-api/vite-plugin build && bun run -F @devup-api/next-plugin build && bun run -F @devup-api/rsbuild-plugin build", - "publish": "bun publish --cwd packages/core && bun publish --cwd packages/utils && bun publish --cwd packages/generator && bun publish --cwd packages/fetch && bun publish --cwd packages/webpack-plugin && bun publish --cwd packages/vite-plugin && bun publish --cwd packages/next-plugin && bun publish --cwd packages/rsbuild-plugin" + "build": "bun run -F @devup-api/core build && bun run -F @devup-api/utils build && bun run -F @devup-api/generator build && bun run -F @devup-api/fetch build && bun run -F @devup-api/webpack-plugin build && bun run -F @devup-api/vite-plugin build && bun run -F @devup-api/next-plugin build && bun run -F @devup-api/rsbuild-plugin build && bun run -F @devup-api/react-query build", + "publish": "bun publish --cwd packages/core && bun publish --cwd packages/utils && bun publish --cwd packages/generator && bun publish --cwd packages/fetch && bun publish --cwd packages/webpack-plugin && bun publish --cwd packages/vite-plugin && bun publish --cwd packages/next-plugin && bun publish --cwd packages/rsbuild-plugin && bun publish --cwd packages/react-query" }, "workspaces": [ "packages/*", diff --git a/packages/core/src/additional.ts b/packages/core/src/additional.ts index 6291af4..ba134e0 100644 --- a/packages/core/src/additional.ts +++ b/packages/core/src/additional.ts @@ -1,3 +1,4 @@ +import type { DevupApiServers } from './api-struct' import type { Middleware } from './middleware' export type Additional< @@ -7,7 +8,14 @@ export type Additional< export type RequiredOptions = keyof T extends undefined ? never - : T + : 'params' extends keyof T + ? T + : 'query' extends keyof T + ? T + : 'body' extends keyof T + ? T + : never +export type IsCold = keyof DevupApiServers extends never ? true : false export type DevupApiRequestInit = Omit & { body?: object | RequestInit['body'] params?: Record diff --git a/packages/core/src/api-struct.ts b/packages/core/src/api-struct.ts index eff4a61..0035f86 100644 --- a/packages/core/src/api-struct.ts +++ b/packages/core/src/api-struct.ts @@ -24,28 +24,48 @@ export interface DevupRequestComponentStruct {} // biome-ignore lint/suspicious/noEmptyInterface: empty interface export interface DevupResponseComponentStruct {} -export type DevupApiStruct = DevupGetApiStruct & - DevupPostApiStruct & - DevupPutApiStruct & - DevupDeleteApiStruct & - DevupPatchApiStruct +export type DevupGetApiStructScope = ConditionalScope< + DevupGetApiStruct, + O +> +export type DevupPostApiStructScope = ConditionalScope< + DevupPostApiStruct, + O +> +export type DevupPutApiStructScope = ConditionalScope< + DevupPutApiStruct, + O +> +export type DevupDeleteApiStructScope = ConditionalScope< + DevupDeleteApiStruct, + O +> +export type DevupPatchApiStructScope = ConditionalScope< + DevupPatchApiStruct, + O +> export type DevupGetApiStructKey = ConditionalKeys< - ConditionalScope + DevupGetApiStructScope > export type DevupPostApiStructKey = ConditionalKeys< - ConditionalScope + DevupPostApiStructScope > export type DevupPutApiStructKey = ConditionalKeys< - ConditionalScope + DevupPutApiStructScope > export type DevupDeleteApiStructKey = ConditionalKeys< - ConditionalScope + DevupDeleteApiStructScope > export type DevupPatchApiStructKey = ConditionalKeys< - ConditionalScope + DevupPatchApiStructScope > +export type DevupApiStructScope = DevupGetApiStructScope & + DevupPostApiStructScope & + DevupPutApiStructScope & + DevupDeleteApiStructScope & + DevupPatchApiStructScope export type DevupApiStructKey = ConditionalKeys< - ConditionalScope + DevupApiStructScope > diff --git a/packages/core/src/middleware.ts b/packages/core/src/middleware.ts index 526a96f..dc8dcb2 100644 --- a/packages/core/src/middleware.ts +++ b/packages/core/src/middleware.ts @@ -11,13 +11,13 @@ export interface MiddlewareCallbackParams { } type MiddlewareOnRequest = ( - params: MiddlewareCallbackParams, + params: Readonly, ) => PromiseOr type MiddlewareOnResponse = ( - params: MiddlewareCallbackParams & { response: Response }, + params: Readonly, ) => PromiseOr type MiddlewareOnError = ( - params: MiddlewareCallbackParams & { error: unknown }, + params: Readonly, ) => PromiseOr export type Middleware = diff --git a/packages/fetch/src/__tests__/api.test.ts b/packages/fetch/src/__tests__/api.test.ts index 20a663b..14658c1 100644 --- a/packages/fetch/src/__tests__/api.test.ts +++ b/packages/fetch/src/__tests__/api.test.ts @@ -131,6 +131,28 @@ test('request does not serialize non-plain object body', async () => { } }) +test('request serializes plain object body to JSON with custom headers', async () => { + const api = new DevupApi('https://api.example.com', undefined, 'openapi.json') + const mockFetch = globalThis.fetch as unknown as ReturnType + + await api.post( + '/test' as never, + { + body: { name: 'test', value: 123 }, + } as never, + ) + + expect(mockFetch).toHaveBeenCalledTimes(1) + const call = mockFetch.mock.calls[0] + expect(call).toBeDefined() + if (call) { + const request = call[0] as Request + const body = await request.text() + expect(body).toBe(JSON.stringify({ name: 'test', value: 123 })) + expect(request.headers.get('Content-Type')).toBe('application/json') + } +}) + test('request merges defaultOptions with request options', async () => { const api = new DevupApi( 'https://api.example.com', diff --git a/packages/fetch/src/api.ts b/packages/fetch/src/api.ts index 1990f39..99fdc18 100644 --- a/packages/fetch/src/api.ts +++ b/packages/fetch/src/api.ts @@ -1,22 +1,22 @@ import type { Additional, ConditionalKeys, - ConditionalScope, DevupApiRequestInit, DevupApiServers, - DevupApiStruct, DevupApiStructKey, - DevupDeleteApiStruct, + DevupApiStructScope, DevupDeleteApiStructKey, - DevupGetApiStruct, + DevupDeleteApiStructScope, DevupGetApiStructKey, - DevupPatchApiStruct, + DevupGetApiStructScope, DevupPatchApiStructKey, - DevupPostApiStruct, + DevupPatchApiStructScope, DevupPostApiStructKey, - DevupPutApiStruct, + DevupPostApiStructScope, DevupPutApiStructKey, + DevupPutApiStructScope, ExtractValue, + IsCold, Middleware, RequiredOptions, } from '@devup-api/core' @@ -56,12 +56,20 @@ export class DevupApi> { get< T extends DevupGetApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -73,12 +81,20 @@ export class DevupApi> { GET< T extends DevupGetApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -90,12 +106,20 @@ export class DevupApi> { post< T extends DevupPostApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -107,12 +131,20 @@ export class DevupApi> { POST< T extends DevupPostApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -124,12 +156,20 @@ export class DevupApi> { put< T extends DevupPutApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -141,12 +181,20 @@ export class DevupApi> { PUT< T extends DevupPutApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -158,12 +206,20 @@ export class DevupApi> { delete< T extends DevupDeleteApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -175,12 +231,20 @@ export class DevupApi> { DELETE< T extends DevupDeleteApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -192,12 +256,20 @@ export class DevupApi> { patch< T extends DevupPatchApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -209,12 +281,20 @@ export class DevupApi> { PATCH< T extends DevupPatchApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -226,17 +306,33 @@ export class DevupApi> { async request< T extends DevupApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { const { method, url } = getApiEndpointInfo(path, this.serverName) - const { middleware = [], query, ...restOptions } = options[0] || {} + const { + middleware = [], + query, + headers = {}, + body, + params, + ...restOptions + }: DevupApiRequestInit = options[0] || {} + const mergedHeaders = new Headers(headers) const mergedOptions = { ...this.defaultOptions, ...restOptions, @@ -244,24 +340,21 @@ export class DevupApi> { const requestOptions = { ...mergedOptions, method: mergedOptions.method || method, + headers: mergedHeaders, } - if (requestOptions.body && isPlainObject(requestOptions.body)) { - requestOptions.body = JSON.stringify(requestOptions.body) + if (body) { + if (isPlainObject(body)) { + requestOptions.body = JSON.stringify(body) + if (!requestOptions.headers.has('Content-Type')) { + requestOptions.headers.set('Content-Type', 'application/json') + } + } else { + requestOptions.body = body + } } const queryString = query ? `?${getQueryString(query).toString()}` : '' let request = new Request( - getApiEndpoint( - this.baseUrl, - url, - ( - requestOptions as { - params?: Record< - string, - string | number | boolean | null | undefined - > - } - ).params, - ) + queryString, + getApiEndpoint(this.baseUrl, url, params) + queryString, requestOptions as RequestInit, ) @@ -271,14 +364,16 @@ export class DevupApi> { for (const middleware of finalMiddleware) { if (middleware.onRequest) { - const result = await middleware.onRequest({ - request, - schemaPath: url, - params: requestOptions.params, - query: requestOptions.query, - headers: requestOptions.headers, - body: requestOptions.body, - }) + const result = await middleware.onRequest( + Object.freeze({ + request, + schemaPath: url, + params, + query, + headers, + body, + }), + ) if (result) { if (result instanceof Request) { request = result @@ -348,19 +443,19 @@ export class DevupApi> { } as DevupApiResponse, ExtractValue> } - setDefaultOptions(options: DevupApiRequestInit) { + setDefaultOptions(options: DevupApiRequestInit): void { this.defaultOptions = options } - getBaseUrl() { + getBaseUrl(): string { return this.baseUrl } - getDefaultOptions() { + getDefaultOptions(): DevupApiRequestInit { return this.defaultOptions } - use(...middleware: Middleware[]) { + use(...middleware: Middleware[]): void { this.middleware.push(...middleware) } } diff --git a/packages/fetch/src/create-api.ts b/packages/fetch/src/create-api.ts index 6c47de6..0305302 100644 --- a/packages/fetch/src/create-api.ts +++ b/packages/fetch/src/create-api.ts @@ -4,13 +4,18 @@ import { DevupApi } from './api' // Implementation export function createApi< S extends ConditionalKeys = 'openapi.json', ->({ - baseUrl = '', - serverName = 'openapi.json' as S, - ...defaultOptions -}: { - baseUrl?: string - serverName?: S -} & RequestInit = {}): DevupApi { +>( + options: + | string + | ({ + baseUrl?: string + serverName?: S + } & RequestInit), +): DevupApi { + const { + baseUrl = '', + serverName = 'openapi.json' as S, + ...defaultOptions + } = typeof options === 'string' ? { baseUrl: options } : options return new DevupApi(baseUrl, defaultOptions, serverName) } diff --git a/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap b/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap index b7376d3..c4dca56 100644 --- a/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap +++ b/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap @@ -560,11 +560,11 @@ declare module "@devup-api/fetch" { interface DevupPostApiStruct { [\`openapi.json\`]: { [\`/users\`]: { - body: DevupRequestComponentStruct['User']; + body: DevupRequestComponentStruct['openapi.json']['User']; response?: {}; }; createUser: { - body: DevupRequestComponentStruct['User']; + body: DevupRequestComponentStruct['openapi.json']['User']; response?: {}; }; } @@ -768,11 +768,11 @@ declare module "@devup-api/fetch" { interface DevupPostApiStruct { [\`openapi.json\`]: { [\`/users\`]: { - body: DevupRequestComponentStruct['CreateUserRequest']; + body: DevupRequestComponentStruct['openapi.json']['CreateUserRequest']; response?: {}; }; createUser: { - body: DevupRequestComponentStruct['CreateUserRequest']; + body: DevupRequestComponentStruct['openapi.json']['CreateUserRequest']; response?: {}; }; } @@ -1277,14 +1277,14 @@ declare module "@devup-api/fetch" { params: { userId: string; }; - body: DevupRequestComponentStruct['UpdatePostRequest']; + body: DevupRequestComponentStruct['openapi.json']['UpdatePostRequest']; response: DevupResponseComponentStruct['openapi.json']['Post']; }; updateUserPost: { params: { userId: string; }; - body: DevupRequestComponentStruct['UpdatePostRequest']; + body: DevupRequestComponentStruct['openapi.json']['UpdatePostRequest']; response: DevupResponseComponentStruct['openapi.json']['Post']; }; } diff --git a/packages/generator/src/generate-interface.ts b/packages/generator/src/generate-interface.ts index 10b2a0e..9335d24 100644 --- a/packages/generator/src/generate-interface.ts +++ b/packages/generator/src/generate-interface.ts @@ -256,7 +256,7 @@ function generateSchemaInterface( requestSchemaNames.has(schemaName) ) { // Use component reference - requestBodyType = `DevupRequestComponentStruct['${schemaName}']` + requestBodyType = `DevupRequestComponentStruct['${serverName}']['${schemaName}']` } else { const requestBody = extractRequestBody( operation.requestBody, diff --git a/packages/react-query/src/__tests__/query-client.test.tsx b/packages/react-query/src/__tests__/query-client.test.tsx index f074d35..0311d81 100644 --- a/packages/react-query/src/__tests__/query-client.test.tsx +++ b/packages/react-query/src/__tests__/query-client.test.tsx @@ -206,7 +206,7 @@ test('DevupQueryClient useInfiniteQuery with GET method', async () => { const { result } = renderHook( () => - queryClient.useInfiniteQuery('get', '/test' as any, undefined, { + queryClient.useInfiniteQuery('get', '/test' as any, { initialPageParam: 1, getNextPageParam: () => undefined, }), @@ -232,17 +232,11 @@ test('DevupQueryClient useInfiniteQuery with options', async () => { const { result } = renderHook( () => - queryClient.useInfiniteQuery( - 'get', - '/test' as any, - { - query: { page: 1 }, - }, - { - initialPageParam: 1, - getNextPageParam: () => undefined, - }, - ), + queryClient.useInfiniteQuery('get', '/test' as any, { + initialPageParam: 1, + getNextPageParam: () => undefined, + query: { page: 1 }, + }), { wrapper: createWrapper() }, ) @@ -267,7 +261,7 @@ test('DevupQueryClient useQuery with different HTTP methods', async () => { for (const method of methods) { const { result } = renderHook( - () => queryClient.useQuery(method as any, '/test' as any), + () => queryClient.useQuery(method as any, '/test' as any, {}), { wrapper: createWrapper() }, ) @@ -317,7 +311,7 @@ test('DevupQueryClient useSuspenseQuery with different HTTP methods', async () = for (const method of methods) { const { result } = renderHook( - () => queryClient.useSuspenseQuery(method as any, '/test' as any), + () => queryClient.useSuspenseQuery(method as any, '/test' as any, {}), { wrapper: createWrapper() }, ) @@ -341,7 +335,7 @@ test('DevupQueryClient useInfiniteQuery with different HTTP methods', async () = for (const method of methods) { const { result } = renderHook( () => - queryClient.useInfiniteQuery(method as any, '/test' as any, undefined, { + queryClient.useInfiniteQuery(method as any, '/test' as any, { initialPageParam: 1, getNextPageParam: () => undefined, }), diff --git a/packages/react-query/src/create-query-client.ts b/packages/react-query/src/create-query-client.ts index 6519bba..9a87058 100644 --- a/packages/react-query/src/create-query-client.ts +++ b/packages/react-query/src/create-query-client.ts @@ -1,5 +1,8 @@ -import type { ConditionalKeys } from '@devup-api/core' -import type { DevupApi, DevupApiServers } from '@devup-api/fetch' +import type { + ConditionalKeys, + DevupApi, + DevupApiServers, +} from '@devup-api/fetch' import { DevupQueryClient } from './query-client' export function createQueryClient>( diff --git a/packages/react-query/src/query-client.ts b/packages/react-query/src/query-client.ts index 44d5a24..a947e06 100644 --- a/packages/react-query/src/query-client.ts +++ b/packages/react-query/src/query-client.ts @@ -1,25 +1,19 @@ import type { Additional, ConditionalKeys, - ConditionalScope, DevupApi, DevupApiRequestInit, DevupApiResponse, DevupApiServers, - DevupApiStruct, - DevupApiStructKey, - DevupDeleteApiStruct, - DevupDeleteApiStructKey, - DevupGetApiStruct, - DevupGetApiStructKey, - DevupPatchApiStruct, - DevupPatchApiStructKey, - DevupPostApiStruct, - DevupPostApiStructKey, - DevupPutApiStruct, - DevupPutApiStructKey, + DevupDeleteApiStructScope, + DevupGetApiStructScope, + DevupPatchApiStructScope, + DevupPostApiStructScope, + DevupPutApiStructScope, ExtractValue, + IsCold, RequiredOptions, + // RequiredOptions, } from '@devup-api/fetch' import { useInfiniteQuery, @@ -46,147 +40,7 @@ export class DevupQueryClient> { } useQuery< - T extends DevupGetApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'get' | 'GET', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useQuery< - T extends DevupPostApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'post' | 'POST', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useQuery< - T extends DevupPutApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'put' | 'PUT', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useQuery< - T extends DevupPatchApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'patch' | 'PATCH', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useQuery< - T extends DevupDeleteApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'delete' | 'DELETE', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useQuery< - T extends DevupApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: + M extends | 'get' | 'post' | 'put' @@ -197,10 +51,31 @@ export class DevupQueryClient> { | 'PUT' | 'DELETE' | 'PATCH', + ST extends { + get: DevupGetApiStructScope + post: DevupPostApiStructScope + put: DevupPutApiStructScope + delete: DevupDeleteApiStructScope + patch: DevupPatchApiStructScope + GET: DevupGetApiStructScope + POST: DevupPostApiStructScope + PUT: DevupPutApiStructScope + DELETE: DevupDeleteApiStructScope + PATCH: DevupPatchApiStructScope + }[M], + T extends ConditionalKeys, + O extends Additional, + D extends ExtractValue, + E extends ExtractValue, + >( + method: M, path: T, ...options: [RequiredOptions] extends [never] ? [ - options?: DevupApiRequestInit, + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -208,7 +83,8 @@ export class DevupQueryClient> { queryClient?: Parameters>[1], ] : [ - options: DevupApiRequestInit & Omit, + options: Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -240,105 +116,7 @@ export class DevupQueryClient> { } useMutation< - T extends DevupGetApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, - >( - method: 'get' | 'GET', - path: T, - queryOptions?: Omit< - Parameters>[0], - 'mutationFn' | 'mutationKey' - >, - queryClient?: Parameters>[1], - ): ReturnType> - - useMutation< - T extends DevupPostApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, - >( - method: 'post' | 'POST', - path: T, - queryOptions?: Omit< - Parameters>[0], - 'mutationFn' | 'mutationKey' - >, - queryClient?: Parameters>[1], - ): ReturnType> - - useMutation< - T extends DevupPutApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, - >( - method: 'put' | 'PUT', - path: T, - queryOptions?: Omit< - Parameters>[0], - 'mutationFn' | 'mutationKey' - >, - queryClient?: Parameters>[1], - ): ReturnType> - - useMutation< - T extends DevupPatchApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, - >( - method: 'patch' | 'PATCH', - path: T, - queryOptions?: Omit< - Parameters>[0], - 'mutationFn' | 'mutationKey' - >, - queryClient?: Parameters>[1], - ): ReturnType> - - useMutation< - T extends DevupDeleteApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, - >( - method: 'delete' | 'DELETE', - path: T, - queryOptions?: Omit< - Parameters>[0], - 'mutationFn' | 'mutationKey' - >, - queryClient?: Parameters>[1], - ): ReturnType> - - useMutation< - T extends DevupApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, - >( - method: + M extends | 'get' | 'post' | 'put' @@ -349,6 +127,32 @@ export class DevupQueryClient> { | 'PUT' | 'DELETE' | 'PATCH', + ST extends { + get: DevupGetApiStructScope + post: DevupPostApiStructScope + put: DevupPutApiStructScope + delete: DevupDeleteApiStructScope + patch: DevupPatchApiStructScope + GET: DevupGetApiStructScope + POST: DevupPostApiStructScope + PUT: DevupPutApiStructScope + DELETE: DevupDeleteApiStructScope + PATCH: DevupPatchApiStructScope + }[M], + T extends ConditionalKeys, + O extends Additional, + D extends ExtractValue, + E extends ExtractValue, + V extends [RequiredOptions] extends [never] + ? + | (IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit) + | undefined + : Omit & Omit, + >( + method: M, path: T, queryOptions?: Omit< Parameters>[0], @@ -374,150 +178,7 @@ export class DevupQueryClient> { } useSuspenseQuery< - T extends DevupGetApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'get' | 'GET', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useSuspenseQuery< - T extends DevupPostApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'post' | 'POST', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useSuspenseQuery< - T extends DevupPutApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'put' | 'PUT', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useSuspenseQuery< - T extends DevupPatchApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'patch' | 'PATCH', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useSuspenseQuery< - T extends DevupDeleteApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'delete' | 'DELETE', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useSuspenseQuery< - T extends DevupApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - OP extends [RequiredOptions] extends [never] - ? DevupApiRequestInit | undefined - : DevupApiRequestInit & Omit, - >( - method: + M extends | 'get' | 'post' | 'put' @@ -528,10 +189,31 @@ export class DevupQueryClient> { | 'PUT' | 'DELETE' | 'PATCH', + ST extends { + get: DevupGetApiStructScope + post: DevupPostApiStructScope + put: DevupPutApiStructScope + delete: DevupDeleteApiStructScope + patch: DevupPatchApiStructScope + GET: DevupGetApiStructScope + POST: DevupPostApiStructScope + PUT: DevupPutApiStructScope + DELETE: DevupDeleteApiStructScope + PATCH: DevupPatchApiStructScope + }[M], + T extends ConditionalKeys, + O extends Additional, + D extends ExtractValue, + E extends ExtractValue, + >( + method: M, path: T, ...options: [RequiredOptions] extends [never] ? [ - options?: OP, + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -539,7 +221,8 @@ export class DevupQueryClient> { queryClient?: Parameters>[1], ] : [ - options: OP, + options: Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -571,147 +254,7 @@ export class DevupQueryClient> { } useInfiniteQuery< - T extends DevupGetApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'get' | 'GET', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useInfiniteQuery< - T extends DevupPostApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'post' | 'POST', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useInfiniteQuery< - T extends DevupPutApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'put' | 'PUT', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useInfiniteQuery< - T extends DevupPatchApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'patch' | 'PATCH', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useInfiniteQuery< - T extends DevupDeleteApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: 'delete' | 'DELETE', - path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - ): ReturnType> - - useInfiniteQuery< - T extends DevupApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: + M extends | 'get' | 'post' | 'put' @@ -722,28 +265,46 @@ export class DevupQueryClient> { | 'PUT' | 'DELETE' | 'PATCH', + ST extends { + get: DevupGetApiStructScope + post: DevupPostApiStructScope + put: DevupPutApiStructScope + delete: DevupDeleteApiStructScope + patch: DevupPatchApiStructScope + GET: DevupGetApiStructScope + POST: DevupPostApiStructScope + PUT: DevupPutApiStructScope + DELETE: DevupDeleteApiStructScope + PATCH: DevupPatchApiStructScope + }[M], + T extends ConditionalKeys, + O extends Additional, + D extends ExtractValue, + E extends ExtractValue, + >( + method: M, path: T, - ...options: [RequiredOptions] extends [never] - ? [ - options?: DevupApiRequestInit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] - : [ - options: DevupApiRequestInit & Omit, - queryOptions?: Omit< - Parameters>[0], - 'queryFn' | 'queryKey' - >, - queryClient?: Parameters>[1], - ] + ...options: [ + options: (IsCold extends true + ? DevupApiRequestInit + : Omit & Omit) & + Pick< + Parameters>[0], + 'getNextPageParam' | 'initialPageParam' + >, + queryOptions?: Omit< + Parameters>[0], + 'queryFn' | 'queryKey' | 'getNextPageParam' | 'initialPageParam' + >, + queryClient?: Parameters>[1], + ] ): ReturnType> { + const { getNextPageParam, initialPageParam, ...apiOptions } = options[0] return useInfiniteQuery( { - queryKey: getQueryKey(method, path, options[0]), + getNextPageParam, + initialPageParam, + queryKey: getQueryKey(method, path, apiOptions), queryFn: ({ queryKey, pageParam, signal }): Promise => { const [methodKey, pathKey, ...restOptions] = queryKey const apiOptions = restOptions[0] as DevupApiRequestInit | undefined