From f2f44ef0774ced81c478ca272a331e13bf1e2a7d Mon Sep 17 00:00:00 2001 From: owjs3901 Date: Thu, 4 Dec 2025 20:58:13 +0900 Subject: [PATCH 1/4] Fix json issue --- bun.lock | 7 +- examples/next/app/page.tsx | 39 +- examples/next/package.json | 1 + packages/core/src/additional.ts | 8 +- packages/core/src/api-struct.ts | 42 +- packages/core/src/middleware.ts | 6 +- packages/fetch/src/__tests__/api.test.ts | 22 + packages/fetch/src/api.ts | 88 +- packages/fetch/src/create-api.ts | 21 +- .../generate-interface.test.ts.snap | 1713 ----------------- .../generate-schema.test.ts.snap | 1006 ---------- packages/generator/src/generate-interface.ts | 2 +- packages/react-query/src/query-client.ts | 602 +----- 13 files changed, 234 insertions(+), 3323 deletions(-) delete mode 100644 packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap delete mode 100644 packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap 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..b6df14a 100644 --- a/examples/next/app/page.tsx +++ b/examples/next/app/page.tsx @@ -1,18 +1,49 @@ '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', + 'getUserById', + { + params: { id: 1 }, + query: { + name: 'John Doe', + }, + }, + ) + + console.info(data, isLoading, error) + + const { + data: data2, + isLoading: isLoading2, + error: error2, + } = queryClient.useQuery('GET', '/users', { + params: { id: 1 }, + }) + + console.info(data2, isLoading2, error2) + useEffect(() => { - api2.get('getUsers2', {}).then((res) => { + api2.get('getUsers2').then((res) => { console.log(res) }) - api.get('getUsers', {}).then((res) => { + api.get('getUsers').then((res) => { console.log(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/packages/core/src/additional.ts b/packages/core/src/additional.ts index 6291af4..eaeb438 100644 --- a/packages/core/src/additional.ts +++ b/packages/core/src/additional.ts @@ -7,7 +7,13 @@ 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 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..297f4d1 100644 --- a/packages/fetch/src/api.ts +++ b/packages/fetch/src/api.ts @@ -1,21 +1,20 @@ 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, Middleware, RequiredOptions, @@ -56,7 +55,7 @@ export class DevupApi> { get< T extends DevupGetApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -73,7 +72,7 @@ export class DevupApi> { GET< T extends DevupGetApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -90,7 +89,7 @@ export class DevupApi> { post< T extends DevupPostApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -107,7 +106,7 @@ export class DevupApi> { POST< T extends DevupPostApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -124,7 +123,7 @@ export class DevupApi> { put< T extends DevupPutApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -141,7 +140,7 @@ export class DevupApi> { PUT< T extends DevupPutApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -158,7 +157,7 @@ export class DevupApi> { delete< T extends DevupDeleteApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -175,7 +174,7 @@ export class DevupApi> { DELETE< T extends DevupDeleteApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -192,7 +191,7 @@ export class DevupApi> { patch< T extends DevupPatchApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -209,7 +208,7 @@ export class DevupApi> { PATCH< T extends DevupPatchApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -226,7 +225,7 @@ export class DevupApi> { async request< T extends DevupApiStructKey, - O extends Additional>, + O extends Additional>, >( path: T, ...options: [RequiredOptions] extends [never] @@ -236,7 +235,15 @@ export class DevupApi> { DevupApiResponse, ExtractValue> > { const { method, url } = getApiEndpointInfo(path, this.serverName) - const { middleware = [], query, ...restOptions } = options[0] || {} + const { + middleware = [], + query, + headers = {}, + body, + params, + ...restOptions + } = options[0] || {} + const mergedHeaders = new Headers(headers) const mergedOptions = { ...this.defaultOptions, ...restOptions, @@ -244,24 +251,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 +275,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 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 deleted file mode 100644 index b7376d3..0000000 --- a/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap +++ /dev/null @@ -1,1713 +0,0 @@ -// Bun Snapshot v1, https://bun.sh/docs/test/snapshots - -exports[`generateInterface returns interface for schema: %s 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - getUsers: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 2`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - GetUsers: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 3`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - get_users: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 4`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - getUsers: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 5`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - getUsers: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 6`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - getUsers: { - response: Array; - }; - } - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - createUser: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 7`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - GetUsers: { - response: Array; - }; - } - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - CreateUser: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 8`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - get_users: { - response: Array; - }; - } - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - create_user: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 9`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - getUsers: { - response: Array; - }; - } - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - createUser: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface returns interface for schema: %s 10`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - getUsers: { - response: Array; - }; - } - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - createUser: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles all HTTP methods 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - getUsers: { - response?: {}; - }; - } - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - createUser: { - response?: {}; - }; - } - } - - interface DevupPutApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - updateUser: { - response?: {}; - }; - } - } - - interface DevupDeleteApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - deleteUser: {}; - } - } - - interface DevupPatchApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - patchUser: { - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles path parameters 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users/{userId}\`]: { - params: { - userId: string; - }; - response?: {}; - }; - getUser: { - params: { - userId: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles query parameters 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - query: { - page?: number; - limit: number; - }; - response?: {}; - }; - getUsers: { - query: { - page?: number; - limit: number; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles path and query parameters together 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users/{userId}/posts\`]: { - params: { - userId: string; - }; - query?: { - page?: number; - }; - response?: {}; - }; - getUserPosts: { - params: { - userId: string; - }; - query?: { - page?: number; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles request body 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body?: { - name?: string; - email?: string; - }; - response?: {}; - }; - createUser: { - body?: { - name?: string; - email?: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles request body with $ref 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body: DevupRequestComponentStruct['User']; - response?: {}; - }; - createUser: { - body: DevupRequestComponentStruct['User']; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct { - [\`openapi.json\`]: { - User: { - name?: string; - email?: string; - }; - } - } - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles 200 response 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - getUsers: { - response: Array; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles 201 response 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - createUser: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles response with other status codes 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: { - message?: string; - }; - }; - getUsers: { - response?: { - message?: string; - }; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles error responses 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - error?: { - error?: string; - }; - }; - getUsers: { - response?: {}; - error?: { - error?: string; - }; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct { - [\`openapi.json\`]: { - Error: { - code?: string; - message?: string; - }; - } - } -}" -`; - -exports[`generateInterface handles default error response 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - error?: { - error?: string; - }; - }; - getUsers: { - response?: {}; - error?: { - error?: string; - }; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles component schemas for request 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body: DevupRequestComponentStruct['CreateUserRequest']; - response?: {}; - }; - createUser: { - body: DevupRequestComponentStruct['CreateUserRequest']; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct { - [\`openapi.json\`]: { - CreateUserRequest: { - name?: string; - email?: string; - }; - } - } - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles component schemas for response 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - getUsers: { - response: DevupResponseComponentStruct['openapi.json']['User']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles component schemas for error 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - error: DevupErrorComponentStruct['Error']; - }; - getUsers: { - response?: {}; - error: DevupErrorComponentStruct['Error']; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct { - [\`openapi.json\`]: { - Error: { - code?: string; - message?: string; - }; - } - } -}" -`; - -exports[`generateInterface handles array response with component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - getUsers: { - response: Array; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface creates both operationId and path keys 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users/{userId}\`]: { - params: { - userId: string; - }; - response?: {}; - }; - getUserById: { - params: { - userId: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles endpoints without operationId 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles requestDefaultNonNullable option 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body?: { - name?: string; - email?: string; - }; - response?: {}; - }; - createUser: { - body?: { - name?: string; - email?: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles requestDefaultNonNullable option 2`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body?: { - name?: string; - email?: string; - }; - response?: {}; - }; - createUser: { - body?: { - name?: string; - email?: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles responseDefaultNonNullable option 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: { - id: string; - name?: string; - }; - }; - getUsers: { - response: { - id: string; - name?: string; - }; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles responseDefaultNonNullable option 2`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: { - id?: string; - name?: string; - }; - }; - getUsers: { - response?: { - id?: string; - name?: string; - }; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles nested schemas in allOf 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: { - id?: string; -} & { - extra?: string; -}; - }; - getUsers: { - response: { - id?: string; -} & { - extra?: string; -}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - Base: { - id?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles empty paths 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles pathItem parameters 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users/{userId}\`]: { - params: { - userId: string; - }; - response?: {}; - }; - getUser: { - params: { - userId: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles requestBody $ref 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body?: { - name?: string; - }; - response?: {}; - }; - createUser: { - body?: { - name?: string; - }; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles response $ref 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - getUsers: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles complex scenario with all features 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users/{userId}/posts/{postId}\`]: { - params: { - userId: string; - postId: string; - }; - query?: { - include?: string; - }; - response: DevupResponseComponentStruct['openapi.json']['Post']; - error: DevupErrorComponentStruct['Error']; - }; - getUserPost: { - params: { - userId: string; - postId: string; - }; - query?: { - include?: string; - }; - response: DevupResponseComponentStruct['openapi.json']['Post']; - error: DevupErrorComponentStruct['Error']; - }; - } - } - - interface DevupPutApiStruct { - [\`openapi.json\`]: { - [\`/users/{userId}/posts/{postId}\`]: { - params: { - userId: string; - }; - body: DevupRequestComponentStruct['UpdatePostRequest']; - response: DevupResponseComponentStruct['openapi.json']['Post']; - }; - updateUserPost: { - params: { - userId: string; - }; - body: DevupRequestComponentStruct['UpdatePostRequest']; - response: DevupResponseComponentStruct['openapi.json']['Post']; - }; - } - } - - interface DevupRequestComponentStruct { - [\`openapi.json\`]: { - UpdatePostRequest: { - title?: string; - content?: string; - }; - } - } - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - Post: { - id?: string; - title?: string; - content?: string; - }; - } - } - - interface DevupErrorComponentStruct { - [\`openapi.json\`]: { - Error: { - code?: string; - message?: string; - }; - } - } -}" -`; - -exports[`generateInterface handles anyOf in schema collection 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: ({ - id?: string; -} | { - id?: string; - role?: string; -}); - }; - getUsers: { - response: ({ - id?: string; -} | { - id?: string; - role?: string; -}); - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - }; - Admin: { - id?: string; - role?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles oneOf in schema collection 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: ({ - id?: string; -} | { - name?: string; -}); - }; - getUsers: { - response: ({ - id?: string; -} | { - name?: string; -}); - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - User: { - id?: string; - }; - Guest: { - name?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles requestBody $ref that extracts schema name 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body: unknown; - response?: {}; - }; - createUser: { - body: unknown; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct { - [\`openapi.json\`]: { - CreateUserRequest: { - name?: string; - }; - } - } - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles response $ref that extracts schema name 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: {}; - getUsers: {}; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct { - [\`openapi.json\`]: { - UserResponse: { - id?: string; - }; - } - } - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles requestBody with $ref that is not a component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupPostApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - body: unknown; - response?: {}; - }; - createUser: { - body: unknown; - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles response with $ref that is not a component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: unknown; - }; - getUsers: { - response: unknown; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles error response with $ref that is not a component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - error: unknown; - }; - getUsers: { - response?: {}; - error: unknown; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles array response with $ref that is not a component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response: Array; - }; - getUsers: { - response: Array; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles error array response with $ref that is not a component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - error: Array; - }; - getUsers: { - response?: {}; - error: Array; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles error array response with component schema 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - error: Array; - }; - getUsers: { - response?: {}; - error: Array; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct { - [\`openapi.json\`]: { - Error: { - code?: string; - message?: string; - }; - } - } -}" -`; - -exports[`generateInterface handles error response with $ref to response object 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - getUsers: { - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct {} -}" -`; - -exports[`generateInterface handles error response $ref that extracts schema name 1`] = ` -"import "@devup-api/fetch"; - -declare module "@devup-api/fetch" { - interface DevupApiServers { - [\`openapi.json\`]: never - } - - interface DevupGetApiStruct { - [\`openapi.json\`]: { - [\`/users\`]: { - response?: {}; - }; - getUsers: { - response?: {}; - }; - } - } - - interface DevupRequestComponentStruct {} - - interface DevupResponseComponentStruct {} - - interface DevupErrorComponentStruct { - [\`openapi.json\`]: { - ServerError: { - error?: string; - }; - } - } -}" -`; diff --git a/packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap b/packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap deleted file mode 100644 index 11f9756..0000000 --- a/packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap +++ /dev/null @@ -1,1006 +0,0 @@ -// Bun Snapshot v1, https://bun.sh/docs/test/snapshots - -exports[`getTypeFromSchema returns interface for schema: %s 1`] = ` -{ - "default": undefined, - "type": { - "id?": { - "default": undefined, - "type": "string", - }, - "name?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 2`] = ` -{ - "default": undefined, - "type": { - "id?": { - "default": undefined, - "type": "string", - }, - "name?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 3`] = ` -{ - "default": undefined, - "type": { - "id": { - "default": undefined, - "type": "string", - }, - "name": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 4`] = ` -{ - "default": undefined, - "type": { - "id": { - "default": undefined, - "type": "string", - }, - "name": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 5`] = ` -{ - "default": undefined, - "type": { - "id?": { - "default": "123", - "type": "string", - }, - "name?": { - "default": "John Doe", - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 6`] = ` -{ - "default": undefined, - "type": { - "id": { - "default": "123", - "type": "string", - }, - "name": { - "default": "John Doe", - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 7`] = ` -{ - "default": undefined, - "type": { - "id?": { - "default": "123", - "type": "string", - }, - "name?": { - "default": "John Doe", - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 8`] = ` -{ - "default": undefined, - "type": { - "id": { - "default": "123", - "type": "string", - }, - "name": { - "default": "John Doe", - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 9`] = ` -{ - "default": undefined, - "type": -"Array<{ - id?: string; - name?: string; -}>" -, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 10`] = ` -{ - "default": undefined, - "type": -"Array<{ - id?: string; - name?: string; -}>" -, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 11`] = ` -{ - "default": undefined, - "type": "Array", -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 12`] = ` -{ - "default": undefined, - "type": "Array", -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 13`] = ` -{ - "default": undefined, - "type": -"Array<{ - id?: string; - name?: string; -}>" -, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 14`] = ` -{ - "default": undefined, - "type": -"Array<{ - id?: string; - name?: string; -}>" -, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 15`] = ` -{ - "default": undefined, - "type": -"Array<{ - id?: string; - name?: string; -}>" -, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 16`] = ` -{ - "default": undefined, - "type": -"Array<{ - id: string; - name: string; -}>" -, -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 17`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 18`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 19`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema returns interface for schema: %s 20`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema handles allOf 1`] = ` -{ - "default": undefined, - "type": -"{ - id?: string; -} & { - name?: string; -}" -, -} -`; - -exports[`getTypeFromSchema handles empty allOf 1`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema handles allOf with default 1`] = ` -{ - "default": { - "id": "123", - }, - "type": -"{ - id?: string; -}" -, -} -`; - -exports[`getTypeFromSchema handles anyOf 1`] = ` -{ - "default": undefined, - "type": "(string | number)", -} -`; - -exports[`getTypeFromSchema handles empty anyOf 1`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema handles anyOf with default 1`] = ` -{ - "default": "test", - "type": "(string)", -} -`; - -exports[`getTypeFromSchema handles oneOf 1`] = ` -{ - "default": undefined, - "type": "(string | number)", -} -`; - -exports[`getTypeFromSchema handles empty oneOf 1`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema handles enum 1`] = ` -{ - "default": undefined, - "type": ""red" | "green" | "blue"", -} -`; - -exports[`getTypeFromSchema handles enum with default 1`] = ` -{ - "default": "red", - "type": ""red" | "green" | "blue"", -} -`; - -exports[`getTypeFromSchema handles enum with number values 1`] = ` -{ - "default": undefined, - "type": ""1" | "2" | "3"", -} -`; - -exports[`getTypeFromSchema handles number type 1`] = ` -{ - "default": undefined, - "type": "number", -} -`; - -exports[`getTypeFromSchema handles number type with default 1`] = ` -{ - "default": 42, - "type": "number", -} -`; - -exports[`getTypeFromSchema handles integer type 1`] = ` -{ - "default": undefined, - "type": "number", -} -`; - -exports[`getTypeFromSchema handles integer type with default 1`] = ` -{ - "default": 10, - "type": "number", -} -`; - -exports[`getTypeFromSchema handles boolean type 1`] = ` -{ - "default": undefined, - "type": "boolean", -} -`; - -exports[`getTypeFromSchema handles boolean type with default 1`] = ` -{ - "default": true, - "type": "boolean", -} -`; - -exports[`getTypeFromSchema handles string with date format 1`] = ` -{ - "default": undefined, - "type": "string", -} -`; - -exports[`getTypeFromSchema handles string with date-time format 1`] = ` -{ - "default": undefined, - "type": "string", -} -`; - -exports[`getTypeFromSchema handles string with default 1`] = ` -{ - "default": "test", - "type": "string", -} -`; - -exports[`getTypeFromSchema handles array without items 1`] = ` -{ - "default": undefined, - "type": "unknown[]", -} -`; - -exports[`getTypeFromSchema handles array without items with default 1`] = ` -{ - "default": [], - "type": "unknown[]", -} -`; - -exports[`getTypeFromSchema handles object with additionalProperties true 1`] = ` -{ - "default": undefined, - "type": { - "[key: string]": { - "default": undefined, - "type": "unknown", - }, - "id?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with additionalProperties schema 1`] = ` -{ - "default": undefined, - "type": { - "[key: string]": { - "default": undefined, - "type": "string", - }, - "id?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with additionalProperties schema with default 1`] = ` -{ - "default": undefined, - "type": { - "[key: string]": { - "default": "default", - "type": "string", - }, - "id?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema handles object without properties but with type object 1`] = ` -{ - "default": undefined, - "type": {}, -} -`; - -exports[`getTypeFromSchema handles properties without type object 1`] = ` -{ - "default": undefined, - "type": { - "id?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with property $ref that has default 1`] = ` -{ - "default": undefined, - "type": { - "user?": { - "default": { - "id": "123", - }, - "type": { - "id?": { - "default": undefined, - "type": "string", - }, - }, - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with required property that has default 1`] = ` -{ - "default": undefined, - "type": { - "id": { - "default": "123", - "type": "string", - }, - "name?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with required property that has default 2`] = ` -{ - "default": undefined, - "type": { - "id": { - "default": "123", - "type": "string", - }, - "name?": { - "default": undefined, - "type": "string", - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with property $ref without default 1`] = ` -{ - "default": undefined, - "type": { - "user?": { - "default": undefined, - "type": { - "id?": { - "default": undefined, - "type": "string", - }, - }, - }, - }, -} -`; - -exports[`getTypeFromSchema handles object with property $ref that cannot be resolved 1`] = ` -{ - "default": undefined, - "type": { - "user?": { - "default": undefined, - "type": "unknown", - }, - }, -} -`; - -exports[`getTypeFromSchema handles fallback to unknown 1`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`getTypeFromSchema handles $ref that resolves to schema with $ref 1`] = ` -{ - "default": undefined, - "type": "unknown", -} -`; - -exports[`formatTypeValue handles object 1`] = ` -"{ - id: string; -}" -`; - -exports[`formatTypeValue handles nested type object 1`] = ` -"{ - id: string; -}" -`; - -exports[`formatTypeValue handles ParameterDefinition with description and default 1`] = ` -"{ - /** - * User ID - * @default {123} - */ - id: string; -}" -`; - -exports[`formatTypeValue handles ParameterDefinition with just default 1`] = ` -"{ - /** @default {123} */ - id?: string; -}" -`; - -exports[`formatTypeValue handles ParameterDefinition with description only 1`] = ` -"{ - /** - * User ID - */ - id: string; -}" -`; - -exports[`formatTypeValue handles object with all optional properties 1`] = ` -"{ - id: string; - name: string; -}" -`; - -exports[`formatTypeValue handles nested object with all optional properties 1`] = ` -"{ - user: { - id: string; - name: string; - }; -}" -`; - -exports[`formatTypeValue handles object with string value (component reference) 1`] = ` -"{ - user: User; -}" -`; - -exports[`formatTypeValue handles nested type object with object type 1`] = ` -"{ - id: string; - name: string; -}" -`; - -exports[`formatTypeValue handles object with mixed optional and required 1`] = ` -"{ - required: string; - optional: string; -}" -`; - -exports[`formatTypeValue handles ParameterDefinition with required false 1`] = ` -"{ - page?: number; -}" -`; - -exports[`formatTypeValue handles object with ParameterDefinition that has required true 1`] = ` -"{ - id: string; -}" -`; - -exports[`formatTypeValue handles object with type object that has non-object type 1`] = ` -"{ - id: string; -}" -`; - -exports[`formatTypeValue handles object with nested type object with object type 1`] = ` -"{ - user: { - id: string; - name: string; - }; -}" -`; - -exports[`formatTypeValue handles object with nested regular object 1`] = ` -"{ - user: { - id: string; - name: string; - }; -}" -`; - -exports[`formatTypeValue handles object with non-object value 1`] = ` -"{ - count: 123; -}" -`; - -exports[`formatTypeValue handles object with keys ending with question mark 1`] = ` -"{ - id?: string; - name?: string; -}" -`; - -exports[`formatTypeValue handles object with ParameterDefinition required false in nested check 1`] = ` -"{ - params?: { - page?: number; - }; -}" -`; - -exports[`formatTypeValue handles object with type object containing nested object type 1`] = ` -"{ - user: { - profile: { - id: string; - name: string; - }; - }; -}" -`; - -exports[`formatTypeValue handles object with type object containing non-object type (string) 1`] = ` -"{ - id: string; -}" -`; - -exports[`formatTypeValue handles object with all optional properties (keys ending with ?) 1`] = ` -"{ - params?: { - id?: string; - name?: string; - }; -}" -`; - -exports[`formatTypeValue handles object with nested empty object 1`] = ` -"{ - empty?: {}; -}" -`; - -exports[`formatTypeValue handles object with type object containing nested object with all optional 1`] = ` -"{ - user: { - id?: string; - name?: string; - }; -}" -`; - -exports[`formatTypeValue handles object with type object containing nested object type that triggers recursive areAllPropertiesOptional 1`] = ` -"{ - nested: { - inner: { - id?: string; - name?: string; - }; - }; -}" -`; - -exports[`formatTypeValue handles object with nested regular object that triggers areAllPropertiesOptional recursive call (line 230) 1`] = ` -"{ - nested?: { - id?: string; - name?: string; - }; -}" -`; - -exports[`formatTypeValue handles deeply nested regular objects that trigger areAllPropertiesOptional recursive calls 1`] = ` -"{ - level1?: { - level2?: { - level3?: { - id?: string; - name?: string; - }; - }; - }; -}" -`; - -exports[`formatTypeValue handles object with type object where type is object with optional properties 1`] = ` -"{ - params: { - id?: string; - name?: string; - }; -}" -`; - -exports[`extractParameters handles path parameters 1`] = ` -{ - "headerParams": {}, - "pathParams": { - "id": { - "default": undefined, - "in": "path", - "name": "id", - "required": true, - "schema": { - "type": "string", - }, - "type": "string", - }, - }, - "queryParams": {}, -} -`; - -exports[`extractParameters handles query parameters 1`] = ` -{ - "headerParams": {}, - "pathParams": {}, - "queryParams": { - "page": { - "default": undefined, - "in": "query", - "name": "page", - "required": false, - "schema": { - "type": "number", - }, - "type": "number", - }, - }, -} -`; - -exports[`extractParameters handles header parameters 1`] = ` -{ - "headerParams": { - "Authorization": { - "default": undefined, - "in": "header", - "name": "Authorization", - "required": true, - "schema": { - "type": "string", - }, - "type": "string", - }, - }, - "pathParams": {}, - "queryParams": {}, -} -`; - -exports[`extractParameters handles parameters from both pathItem and operation 1`] = ` -{ - "headerParams": {}, - "pathParams": { - "id": { - "default": undefined, - "in": "path", - "name": "id", - "required": true, - "schema": { - "type": "string", - }, - "type": "string", - }, - }, - "queryParams": { - "page": { - "default": undefined, - "in": "query", - "name": "page", - "required": false, - "schema": { - "type": "number", - }, - "type": "number", - }, - }, -} -`; - -exports[`extractParameters handles $ref parameters 1`] = ` -{ - "headerParams": {}, - "pathParams": { - "id": { - "default": undefined, - "in": "path", - "name": "id", - "required": true, - "schema": { - "type": "string", - }, - "type": "string", - }, - }, - "queryParams": {}, -} -`; - -exports[`extractParameters handles $ref parameter that cannot be resolved 1`] = ` -{ - "headerParams": {}, - "pathParams": {}, - "queryParams": {}, -} -`; - -exports[`extractParameters handles parameter without schema 1`] = ` -{ - "headerParams": {}, - "pathParams": { - "id": { - "default": undefined, - "in": "path", - "name": "id", - "required": true, - "type": "unknown", - }, - }, - "queryParams": {}, -} -`; - -exports[`extractParameters handles $ref parameter without required fields 1`] = ` -{ - "headerParams": {}, - "pathParams": {}, - "queryParams": {}, -} -`; - -exports[`extractParameters handles $ref parameter with schema 1`] = ` -{ - "headerParams": {}, - "pathParams": { - "id": { - "default": "default", - "in": "path", - "name": "id", - "required": true, - "schema": { - "default": "default", - "type": "string", - }, - "type": "string", - }, - }, - "queryParams": {}, -} -`; - -exports[`extractParameters handles $ref query parameter 1`] = ` -{ - "headerParams": {}, - "pathParams": {}, - "queryParams": { - "page": { - "default": undefined, - "in": "query", - "name": "page", - "required": false, - "schema": { - "type": "number", - }, - "type": "number", - }, - }, -} -`; - -exports[`extractParameters handles $ref header parameter 1`] = ` -{ - "headerParams": { - "Authorization": { - "default": undefined, - "in": "header", - "name": "Authorization", - "required": true, - "schema": { - "type": "string", - }, - "type": "string", - }, - }, - "pathParams": {}, - "queryParams": {}, -} -`; - -exports[`extractParameters handles empty parameters 1`] = ` -{ - "headerParams": {}, - "pathParams": {}, - "queryParams": {}, -} -`; - -exports[`extractRequestBody handles requestBody with application/json 1`] = ` -{ - "name?": { - "default": undefined, - "type": "string", - }, -} -`; - -exports[`extractRequestBody handles requestBody $ref 1`] = ` -{ - "name?": { - "default": undefined, - "type": "string", - }, -} -`; 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/query-client.ts b/packages/react-query/src/query-client.ts index 44d5a24..76ca852 100644 --- a/packages/react-query/src/query-client.ts +++ b/packages/react-query/src/query-client.ts @@ -1,23 +1,17 @@ import type { Additional, ConditionalKeys, - ConditionalScope, DevupApi, DevupApiRequestInit, DevupApiResponse, DevupApiServers, - DevupApiStruct, DevupApiStructKey, - DevupDeleteApiStruct, - DevupDeleteApiStructKey, - DevupGetApiStruct, - DevupGetApiStructKey, - DevupPatchApiStruct, - DevupPatchApiStructKey, - DevupPostApiStruct, - DevupPostApiStructKey, - DevupPutApiStruct, - DevupPutApiStructKey, + DevupApiStructScope, + DevupDeleteApiStructScope, + DevupGetApiStructScope, + DevupPatchApiStructScope, + DevupPostApiStructScope, + DevupPutApiStructScope, ExtractValue, RequiredOptions, } from '@devup-api/fetch' @@ -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,6 +51,24 @@ 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] ? [ @@ -240,105 +112,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 +123,27 @@ 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] + ? DevupApiRequestInit + : DevupApiRequestInit & Omit, + >( + method: M, path: T, queryOptions?: Omit< Parameters>[0], @@ -374,150 +169,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,6 +180,27 @@ 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, + OP extends [RequiredOptions] extends [never] + ? DevupApiRequestInit | undefined + : DevupApiRequestInit & Omit, + >( + method: M, path: T, ...options: [RequiredOptions] extends [never] ? [ @@ -570,144 +243,9 @@ 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>, + O extends Additional>, D extends ExtractValue, E extends ExtractValue, >( From d6c110a31d790653e6ec94d843651f001ff21048 Mon Sep 17 00:00:00 2001 From: owjs3901 Date: Thu, 4 Dec 2025 20:58:30 +0900 Subject: [PATCH 2/4] Fix json issue --- .../generate-interface.test.ts.snap | 1713 +++++++++++++++++ .../generate-schema.test.ts.snap | 1006 ++++++++++ 2 files changed, 2719 insertions(+) create mode 100644 packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap create mode 100644 packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap diff --git a/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap b/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap new file mode 100644 index 0000000..c4dca56 --- /dev/null +++ b/packages/generator/src/__tests__/__snapshots__/generate-interface.test.ts.snap @@ -0,0 +1,1713 @@ +// Bun Snapshot v1, https://bun.sh/docs/test/snapshots + +exports[`generateInterface returns interface for schema: %s 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + getUsers: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 2`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + GetUsers: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 3`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + get_users: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 4`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + getUsers: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 5`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + getUsers: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 6`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + getUsers: { + response: Array; + }; + } + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + createUser: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 7`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + GetUsers: { + response: Array; + }; + } + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + CreateUser: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 8`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + get_users: { + response: Array; + }; + } + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + create_user: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 9`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + getUsers: { + response: Array; + }; + } + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + createUser: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface returns interface for schema: %s 10`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + getUsers: { + response: Array; + }; + } + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + createUser: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles all HTTP methods 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + getUsers: { + response?: {}; + }; + } + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + createUser: { + response?: {}; + }; + } + } + + interface DevupPutApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + updateUser: { + response?: {}; + }; + } + } + + interface DevupDeleteApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + deleteUser: {}; + } + } + + interface DevupPatchApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + patchUser: { + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles path parameters 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users/{userId}\`]: { + params: { + userId: string; + }; + response?: {}; + }; + getUser: { + params: { + userId: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles query parameters 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + query: { + page?: number; + limit: number; + }; + response?: {}; + }; + getUsers: { + query: { + page?: number; + limit: number; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles path and query parameters together 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users/{userId}/posts\`]: { + params: { + userId: string; + }; + query?: { + page?: number; + }; + response?: {}; + }; + getUserPosts: { + params: { + userId: string; + }; + query?: { + page?: number; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles request body 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body?: { + name?: string; + email?: string; + }; + response?: {}; + }; + createUser: { + body?: { + name?: string; + email?: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles request body with $ref 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body: DevupRequestComponentStruct['openapi.json']['User']; + response?: {}; + }; + createUser: { + body: DevupRequestComponentStruct['openapi.json']['User']; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct { + [\`openapi.json\`]: { + User: { + name?: string; + email?: string; + }; + } + } + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles 200 response 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + getUsers: { + response: Array; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles 201 response 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + createUser: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles response with other status codes 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: { + message?: string; + }; + }; + getUsers: { + response?: { + message?: string; + }; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles error responses 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + error?: { + error?: string; + }; + }; + getUsers: { + response?: {}; + error?: { + error?: string; + }; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct { + [\`openapi.json\`]: { + Error: { + code?: string; + message?: string; + }; + } + } +}" +`; + +exports[`generateInterface handles default error response 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + error?: { + error?: string; + }; + }; + getUsers: { + response?: {}; + error?: { + error?: string; + }; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles component schemas for request 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body: DevupRequestComponentStruct['openapi.json']['CreateUserRequest']; + response?: {}; + }; + createUser: { + body: DevupRequestComponentStruct['openapi.json']['CreateUserRequest']; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct { + [\`openapi.json\`]: { + CreateUserRequest: { + name?: string; + email?: string; + }; + } + } + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles component schemas for response 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + getUsers: { + response: DevupResponseComponentStruct['openapi.json']['User']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles component schemas for error 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + error: DevupErrorComponentStruct['Error']; + }; + getUsers: { + response?: {}; + error: DevupErrorComponentStruct['Error']; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct { + [\`openapi.json\`]: { + Error: { + code?: string; + message?: string; + }; + } + } +}" +`; + +exports[`generateInterface handles array response with component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + getUsers: { + response: Array; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface creates both operationId and path keys 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users/{userId}\`]: { + params: { + userId: string; + }; + response?: {}; + }; + getUserById: { + params: { + userId: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles endpoints without operationId 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles requestDefaultNonNullable option 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body?: { + name?: string; + email?: string; + }; + response?: {}; + }; + createUser: { + body?: { + name?: string; + email?: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles requestDefaultNonNullable option 2`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body?: { + name?: string; + email?: string; + }; + response?: {}; + }; + createUser: { + body?: { + name?: string; + email?: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles responseDefaultNonNullable option 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: { + id: string; + name?: string; + }; + }; + getUsers: { + response: { + id: string; + name?: string; + }; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles responseDefaultNonNullable option 2`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: { + id?: string; + name?: string; + }; + }; + getUsers: { + response?: { + id?: string; + name?: string; + }; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles nested schemas in allOf 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: { + id?: string; +} & { + extra?: string; +}; + }; + getUsers: { + response: { + id?: string; +} & { + extra?: string; +}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + Base: { + id?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles empty paths 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles pathItem parameters 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users/{userId}\`]: { + params: { + userId: string; + }; + response?: {}; + }; + getUser: { + params: { + userId: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles requestBody $ref 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body?: { + name?: string; + }; + response?: {}; + }; + createUser: { + body?: { + name?: string; + }; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles response $ref 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + getUsers: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles complex scenario with all features 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users/{userId}/posts/{postId}\`]: { + params: { + userId: string; + postId: string; + }; + query?: { + include?: string; + }; + response: DevupResponseComponentStruct['openapi.json']['Post']; + error: DevupErrorComponentStruct['Error']; + }; + getUserPost: { + params: { + userId: string; + postId: string; + }; + query?: { + include?: string; + }; + response: DevupResponseComponentStruct['openapi.json']['Post']; + error: DevupErrorComponentStruct['Error']; + }; + } + } + + interface DevupPutApiStruct { + [\`openapi.json\`]: { + [\`/users/{userId}/posts/{postId}\`]: { + params: { + userId: string; + }; + body: DevupRequestComponentStruct['openapi.json']['UpdatePostRequest']; + response: DevupResponseComponentStruct['openapi.json']['Post']; + }; + updateUserPost: { + params: { + userId: string; + }; + body: DevupRequestComponentStruct['openapi.json']['UpdatePostRequest']; + response: DevupResponseComponentStruct['openapi.json']['Post']; + }; + } + } + + interface DevupRequestComponentStruct { + [\`openapi.json\`]: { + UpdatePostRequest: { + title?: string; + content?: string; + }; + } + } + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + Post: { + id?: string; + title?: string; + content?: string; + }; + } + } + + interface DevupErrorComponentStruct { + [\`openapi.json\`]: { + Error: { + code?: string; + message?: string; + }; + } + } +}" +`; + +exports[`generateInterface handles anyOf in schema collection 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: ({ + id?: string; +} | { + id?: string; + role?: string; +}); + }; + getUsers: { + response: ({ + id?: string; +} | { + id?: string; + role?: string; +}); + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + }; + Admin: { + id?: string; + role?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles oneOf in schema collection 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: ({ + id?: string; +} | { + name?: string; +}); + }; + getUsers: { + response: ({ + id?: string; +} | { + name?: string; +}); + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + User: { + id?: string; + }; + Guest: { + name?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles requestBody $ref that extracts schema name 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body: unknown; + response?: {}; + }; + createUser: { + body: unknown; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct { + [\`openapi.json\`]: { + CreateUserRequest: { + name?: string; + }; + } + } + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles response $ref that extracts schema name 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: {}; + getUsers: {}; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct { + [\`openapi.json\`]: { + UserResponse: { + id?: string; + }; + } + } + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles requestBody with $ref that is not a component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupPostApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + body: unknown; + response?: {}; + }; + createUser: { + body: unknown; + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles response with $ref that is not a component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: unknown; + }; + getUsers: { + response: unknown; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles error response with $ref that is not a component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + error: unknown; + }; + getUsers: { + response?: {}; + error: unknown; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles array response with $ref that is not a component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response: Array; + }; + getUsers: { + response: Array; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles error array response with $ref that is not a component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + error: Array; + }; + getUsers: { + response?: {}; + error: Array; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles error array response with component schema 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + error: Array; + }; + getUsers: { + response?: {}; + error: Array; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct { + [\`openapi.json\`]: { + Error: { + code?: string; + message?: string; + }; + } + } +}" +`; + +exports[`generateInterface handles error response with $ref to response object 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + getUsers: { + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct {} +}" +`; + +exports[`generateInterface handles error response $ref that extracts schema name 1`] = ` +"import "@devup-api/fetch"; + +declare module "@devup-api/fetch" { + interface DevupApiServers { + [\`openapi.json\`]: never + } + + interface DevupGetApiStruct { + [\`openapi.json\`]: { + [\`/users\`]: { + response?: {}; + }; + getUsers: { + response?: {}; + }; + } + } + + interface DevupRequestComponentStruct {} + + interface DevupResponseComponentStruct {} + + interface DevupErrorComponentStruct { + [\`openapi.json\`]: { + ServerError: { + error?: string; + }; + } + } +}" +`; diff --git a/packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap b/packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap new file mode 100644 index 0000000..11f9756 --- /dev/null +++ b/packages/generator/src/__tests__/__snapshots__/generate-schema.test.ts.snap @@ -0,0 +1,1006 @@ +// Bun Snapshot v1, https://bun.sh/docs/test/snapshots + +exports[`getTypeFromSchema returns interface for schema: %s 1`] = ` +{ + "default": undefined, + "type": { + "id?": { + "default": undefined, + "type": "string", + }, + "name?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 2`] = ` +{ + "default": undefined, + "type": { + "id?": { + "default": undefined, + "type": "string", + }, + "name?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 3`] = ` +{ + "default": undefined, + "type": { + "id": { + "default": undefined, + "type": "string", + }, + "name": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 4`] = ` +{ + "default": undefined, + "type": { + "id": { + "default": undefined, + "type": "string", + }, + "name": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 5`] = ` +{ + "default": undefined, + "type": { + "id?": { + "default": "123", + "type": "string", + }, + "name?": { + "default": "John Doe", + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 6`] = ` +{ + "default": undefined, + "type": { + "id": { + "default": "123", + "type": "string", + }, + "name": { + "default": "John Doe", + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 7`] = ` +{ + "default": undefined, + "type": { + "id?": { + "default": "123", + "type": "string", + }, + "name?": { + "default": "John Doe", + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 8`] = ` +{ + "default": undefined, + "type": { + "id": { + "default": "123", + "type": "string", + }, + "name": { + "default": "John Doe", + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 9`] = ` +{ + "default": undefined, + "type": +"Array<{ + id?: string; + name?: string; +}>" +, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 10`] = ` +{ + "default": undefined, + "type": +"Array<{ + id?: string; + name?: string; +}>" +, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 11`] = ` +{ + "default": undefined, + "type": "Array", +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 12`] = ` +{ + "default": undefined, + "type": "Array", +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 13`] = ` +{ + "default": undefined, + "type": +"Array<{ + id?: string; + name?: string; +}>" +, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 14`] = ` +{ + "default": undefined, + "type": +"Array<{ + id?: string; + name?: string; +}>" +, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 15`] = ` +{ + "default": undefined, + "type": +"Array<{ + id?: string; + name?: string; +}>" +, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 16`] = ` +{ + "default": undefined, + "type": +"Array<{ + id: string; + name: string; +}>" +, +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 17`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 18`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 19`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema returns interface for schema: %s 20`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema handles allOf 1`] = ` +{ + "default": undefined, + "type": +"{ + id?: string; +} & { + name?: string; +}" +, +} +`; + +exports[`getTypeFromSchema handles empty allOf 1`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema handles allOf with default 1`] = ` +{ + "default": { + "id": "123", + }, + "type": +"{ + id?: string; +}" +, +} +`; + +exports[`getTypeFromSchema handles anyOf 1`] = ` +{ + "default": undefined, + "type": "(string | number)", +} +`; + +exports[`getTypeFromSchema handles empty anyOf 1`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema handles anyOf with default 1`] = ` +{ + "default": "test", + "type": "(string)", +} +`; + +exports[`getTypeFromSchema handles oneOf 1`] = ` +{ + "default": undefined, + "type": "(string | number)", +} +`; + +exports[`getTypeFromSchema handles empty oneOf 1`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema handles enum 1`] = ` +{ + "default": undefined, + "type": ""red" | "green" | "blue"", +} +`; + +exports[`getTypeFromSchema handles enum with default 1`] = ` +{ + "default": "red", + "type": ""red" | "green" | "blue"", +} +`; + +exports[`getTypeFromSchema handles enum with number values 1`] = ` +{ + "default": undefined, + "type": ""1" | "2" | "3"", +} +`; + +exports[`getTypeFromSchema handles number type 1`] = ` +{ + "default": undefined, + "type": "number", +} +`; + +exports[`getTypeFromSchema handles number type with default 1`] = ` +{ + "default": 42, + "type": "number", +} +`; + +exports[`getTypeFromSchema handles integer type 1`] = ` +{ + "default": undefined, + "type": "number", +} +`; + +exports[`getTypeFromSchema handles integer type with default 1`] = ` +{ + "default": 10, + "type": "number", +} +`; + +exports[`getTypeFromSchema handles boolean type 1`] = ` +{ + "default": undefined, + "type": "boolean", +} +`; + +exports[`getTypeFromSchema handles boolean type with default 1`] = ` +{ + "default": true, + "type": "boolean", +} +`; + +exports[`getTypeFromSchema handles string with date format 1`] = ` +{ + "default": undefined, + "type": "string", +} +`; + +exports[`getTypeFromSchema handles string with date-time format 1`] = ` +{ + "default": undefined, + "type": "string", +} +`; + +exports[`getTypeFromSchema handles string with default 1`] = ` +{ + "default": "test", + "type": "string", +} +`; + +exports[`getTypeFromSchema handles array without items 1`] = ` +{ + "default": undefined, + "type": "unknown[]", +} +`; + +exports[`getTypeFromSchema handles array without items with default 1`] = ` +{ + "default": [], + "type": "unknown[]", +} +`; + +exports[`getTypeFromSchema handles object with additionalProperties true 1`] = ` +{ + "default": undefined, + "type": { + "[key: string]": { + "default": undefined, + "type": "unknown", + }, + "id?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with additionalProperties schema 1`] = ` +{ + "default": undefined, + "type": { + "[key: string]": { + "default": undefined, + "type": "string", + }, + "id?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with additionalProperties schema with default 1`] = ` +{ + "default": undefined, + "type": { + "[key: string]": { + "default": "default", + "type": "string", + }, + "id?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema handles object without properties but with type object 1`] = ` +{ + "default": undefined, + "type": {}, +} +`; + +exports[`getTypeFromSchema handles properties without type object 1`] = ` +{ + "default": undefined, + "type": { + "id?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with property $ref that has default 1`] = ` +{ + "default": undefined, + "type": { + "user?": { + "default": { + "id": "123", + }, + "type": { + "id?": { + "default": undefined, + "type": "string", + }, + }, + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with required property that has default 1`] = ` +{ + "default": undefined, + "type": { + "id": { + "default": "123", + "type": "string", + }, + "name?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with required property that has default 2`] = ` +{ + "default": undefined, + "type": { + "id": { + "default": "123", + "type": "string", + }, + "name?": { + "default": undefined, + "type": "string", + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with property $ref without default 1`] = ` +{ + "default": undefined, + "type": { + "user?": { + "default": undefined, + "type": { + "id?": { + "default": undefined, + "type": "string", + }, + }, + }, + }, +} +`; + +exports[`getTypeFromSchema handles object with property $ref that cannot be resolved 1`] = ` +{ + "default": undefined, + "type": { + "user?": { + "default": undefined, + "type": "unknown", + }, + }, +} +`; + +exports[`getTypeFromSchema handles fallback to unknown 1`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`getTypeFromSchema handles $ref that resolves to schema with $ref 1`] = ` +{ + "default": undefined, + "type": "unknown", +} +`; + +exports[`formatTypeValue handles object 1`] = ` +"{ + id: string; +}" +`; + +exports[`formatTypeValue handles nested type object 1`] = ` +"{ + id: string; +}" +`; + +exports[`formatTypeValue handles ParameterDefinition with description and default 1`] = ` +"{ + /** + * User ID + * @default {123} + */ + id: string; +}" +`; + +exports[`formatTypeValue handles ParameterDefinition with just default 1`] = ` +"{ + /** @default {123} */ + id?: string; +}" +`; + +exports[`formatTypeValue handles ParameterDefinition with description only 1`] = ` +"{ + /** + * User ID + */ + id: string; +}" +`; + +exports[`formatTypeValue handles object with all optional properties 1`] = ` +"{ + id: string; + name: string; +}" +`; + +exports[`formatTypeValue handles nested object with all optional properties 1`] = ` +"{ + user: { + id: string; + name: string; + }; +}" +`; + +exports[`formatTypeValue handles object with string value (component reference) 1`] = ` +"{ + user: User; +}" +`; + +exports[`formatTypeValue handles nested type object with object type 1`] = ` +"{ + id: string; + name: string; +}" +`; + +exports[`formatTypeValue handles object with mixed optional and required 1`] = ` +"{ + required: string; + optional: string; +}" +`; + +exports[`formatTypeValue handles ParameterDefinition with required false 1`] = ` +"{ + page?: number; +}" +`; + +exports[`formatTypeValue handles object with ParameterDefinition that has required true 1`] = ` +"{ + id: string; +}" +`; + +exports[`formatTypeValue handles object with type object that has non-object type 1`] = ` +"{ + id: string; +}" +`; + +exports[`formatTypeValue handles object with nested type object with object type 1`] = ` +"{ + user: { + id: string; + name: string; + }; +}" +`; + +exports[`formatTypeValue handles object with nested regular object 1`] = ` +"{ + user: { + id: string; + name: string; + }; +}" +`; + +exports[`formatTypeValue handles object with non-object value 1`] = ` +"{ + count: 123; +}" +`; + +exports[`formatTypeValue handles object with keys ending with question mark 1`] = ` +"{ + id?: string; + name?: string; +}" +`; + +exports[`formatTypeValue handles object with ParameterDefinition required false in nested check 1`] = ` +"{ + params?: { + page?: number; + }; +}" +`; + +exports[`formatTypeValue handles object with type object containing nested object type 1`] = ` +"{ + user: { + profile: { + id: string; + name: string; + }; + }; +}" +`; + +exports[`formatTypeValue handles object with type object containing non-object type (string) 1`] = ` +"{ + id: string; +}" +`; + +exports[`formatTypeValue handles object with all optional properties (keys ending with ?) 1`] = ` +"{ + params?: { + id?: string; + name?: string; + }; +}" +`; + +exports[`formatTypeValue handles object with nested empty object 1`] = ` +"{ + empty?: {}; +}" +`; + +exports[`formatTypeValue handles object with type object containing nested object with all optional 1`] = ` +"{ + user: { + id?: string; + name?: string; + }; +}" +`; + +exports[`formatTypeValue handles object with type object containing nested object type that triggers recursive areAllPropertiesOptional 1`] = ` +"{ + nested: { + inner: { + id?: string; + name?: string; + }; + }; +}" +`; + +exports[`formatTypeValue handles object with nested regular object that triggers areAllPropertiesOptional recursive call (line 230) 1`] = ` +"{ + nested?: { + id?: string; + name?: string; + }; +}" +`; + +exports[`formatTypeValue handles deeply nested regular objects that trigger areAllPropertiesOptional recursive calls 1`] = ` +"{ + level1?: { + level2?: { + level3?: { + id?: string; + name?: string; + }; + }; + }; +}" +`; + +exports[`formatTypeValue handles object with type object where type is object with optional properties 1`] = ` +"{ + params: { + id?: string; + name?: string; + }; +}" +`; + +exports[`extractParameters handles path parameters 1`] = ` +{ + "headerParams": {}, + "pathParams": { + "id": { + "default": undefined, + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string", + }, + "type": "string", + }, + }, + "queryParams": {}, +} +`; + +exports[`extractParameters handles query parameters 1`] = ` +{ + "headerParams": {}, + "pathParams": {}, + "queryParams": { + "page": { + "default": undefined, + "in": "query", + "name": "page", + "required": false, + "schema": { + "type": "number", + }, + "type": "number", + }, + }, +} +`; + +exports[`extractParameters handles header parameters 1`] = ` +{ + "headerParams": { + "Authorization": { + "default": undefined, + "in": "header", + "name": "Authorization", + "required": true, + "schema": { + "type": "string", + }, + "type": "string", + }, + }, + "pathParams": {}, + "queryParams": {}, +} +`; + +exports[`extractParameters handles parameters from both pathItem and operation 1`] = ` +{ + "headerParams": {}, + "pathParams": { + "id": { + "default": undefined, + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string", + }, + "type": "string", + }, + }, + "queryParams": { + "page": { + "default": undefined, + "in": "query", + "name": "page", + "required": false, + "schema": { + "type": "number", + }, + "type": "number", + }, + }, +} +`; + +exports[`extractParameters handles $ref parameters 1`] = ` +{ + "headerParams": {}, + "pathParams": { + "id": { + "default": undefined, + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string", + }, + "type": "string", + }, + }, + "queryParams": {}, +} +`; + +exports[`extractParameters handles $ref parameter that cannot be resolved 1`] = ` +{ + "headerParams": {}, + "pathParams": {}, + "queryParams": {}, +} +`; + +exports[`extractParameters handles parameter without schema 1`] = ` +{ + "headerParams": {}, + "pathParams": { + "id": { + "default": undefined, + "in": "path", + "name": "id", + "required": true, + "type": "unknown", + }, + }, + "queryParams": {}, +} +`; + +exports[`extractParameters handles $ref parameter without required fields 1`] = ` +{ + "headerParams": {}, + "pathParams": {}, + "queryParams": {}, +} +`; + +exports[`extractParameters handles $ref parameter with schema 1`] = ` +{ + "headerParams": {}, + "pathParams": { + "id": { + "default": "default", + "in": "path", + "name": "id", + "required": true, + "schema": { + "default": "default", + "type": "string", + }, + "type": "string", + }, + }, + "queryParams": {}, +} +`; + +exports[`extractParameters handles $ref query parameter 1`] = ` +{ + "headerParams": {}, + "pathParams": {}, + "queryParams": { + "page": { + "default": undefined, + "in": "query", + "name": "page", + "required": false, + "schema": { + "type": "number", + }, + "type": "number", + }, + }, +} +`; + +exports[`extractParameters handles $ref header parameter 1`] = ` +{ + "headerParams": { + "Authorization": { + "default": undefined, + "in": "header", + "name": "Authorization", + "required": true, + "schema": { + "type": "string", + }, + "type": "string", + }, + }, + "pathParams": {}, + "queryParams": {}, +} +`; + +exports[`extractParameters handles empty parameters 1`] = ` +{ + "headerParams": {}, + "pathParams": {}, + "queryParams": {}, +} +`; + +exports[`extractRequestBody handles requestBody with application/json 1`] = ` +{ + "name?": { + "default": undefined, + "type": "string", + }, +} +`; + +exports[`extractRequestBody handles requestBody $ref 1`] = ` +{ + "name?": { + "default": undefined, + "type": "string", + }, +} +`; From 30fc3c7f14b955e2e257aa16fdcdd9d153cb30ea Mon Sep 17 00:00:00 2001 From: owjs3901 Date: Thu, 4 Dec 2025 22:14:32 +0900 Subject: [PATCH 3/4] Fix typing issue --- .../changepack_log_TrNXrNzW_2CG0ILlaaUW3.json | 1 + .../changepack_log_c5-e3qOi7k21VRnLuw095.json | 1 + examples/next/app/page.tsx | 26 ++-- package.json | 4 +- packages/core/src/additional.ts | 2 + packages/fetch/src/api.ts | 143 ++++++++++++++---- .../src/__tests__/query-client.test.tsx | 24 ++- packages/react-query/src/query-client.ts | 93 +++++++----- 8 files changed, 202 insertions(+), 92 deletions(-) create mode 100644 .changepacks/changepack_log_TrNXrNzW_2CG0ILlaaUW3.json create mode 100644 .changepacks/changepack_log_c5-e3qOi7k21VRnLuw095.json 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/examples/next/app/page.tsx b/examples/next/app/page.tsx index b6df14a..05bfa8b 100644 --- a/examples/next/app/page.tsx +++ b/examples/next/app/page.tsx @@ -16,34 +16,34 @@ const api2 = createApi({ const queryClient = createQueryClient(api) export default function Home() { - const { data, isLoading, error } = queryClient.useQuery( - 'GET', - 'getUserById', - { - params: { id: 1 }, - query: { - name: 'John Doe', - }, + const { data, isLoading, error } = queryClient.useQuery('GET', 'getUsers', { + // params: { id: 1 }, + query: { + name: 'John Doe', }, - ) + }) console.info(data, isLoading, error) const { data: data2, - isLoading: isLoading2, error: error2, - } = queryClient.useQuery('GET', '/users', { + mutateAsync, + } = queryClient.useMutation('GET', '/users/{id}', {}) + mutateAsync({ params: { id: 1 }, + query: { + name: 'John Doe', + }, }) - console.info(data2, isLoading2, error2) + console.info(data2, error2) useEffect(() => { api2.get('getUsers2').then((res) => { console.log(res) }) - api.get('getUsers').then((res) => { + api.get('getUsers', {}).then((res) => { console.log(res) }) 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 eaeb438..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< @@ -14,6 +15,7 @@ export type RequiredOptions = keyof T extends undefined : '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/fetch/src/api.ts b/packages/fetch/src/api.ts index 297f4d1..99fdc18 100644 --- a/packages/fetch/src/api.ts +++ b/packages/fetch/src/api.ts @@ -16,6 +16,7 @@ import type { DevupPutApiStructKey, DevupPutApiStructScope, ExtractValue, + IsCold, Middleware, RequiredOptions, } from '@devup-api/core' @@ -59,8 +60,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -76,8 +85,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -93,8 +110,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -110,8 +135,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -127,8 +160,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -144,8 +185,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -161,8 +210,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -178,8 +235,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -195,8 +260,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -212,8 +285,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -229,8 +310,16 @@ export class DevupApi> { >( path: T, ...options: [RequiredOptions] extends [never] - ? [options?: DevupApiRequestInit] - : [options: DevupApiRequestInit & Omit] + ? [ + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, + ] + : [ + options: Omit & + Omit, + ] ): Promise< DevupApiResponse, ExtractValue> > { @@ -242,7 +331,7 @@ export class DevupApi> { body, params, ...restOptions - } = options[0] || {} + }: DevupApiRequestInit = options[0] || {} const mergedHeaders = new Headers(headers) const mergedOptions = { ...this.defaultOptions, @@ -354,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/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/query-client.ts b/packages/react-query/src/query-client.ts index 76ca852..a947e06 100644 --- a/packages/react-query/src/query-client.ts +++ b/packages/react-query/src/query-client.ts @@ -5,15 +5,15 @@ import type { DevupApiRequestInit, DevupApiResponse, DevupApiServers, - DevupApiStructKey, - DevupApiStructScope, DevupDeleteApiStructScope, DevupGetApiStructScope, DevupPatchApiStructScope, DevupPostApiStructScope, DevupPutApiStructScope, ExtractValue, + IsCold, RequiredOptions, + // RequiredOptions, } from '@devup-api/fetch' import { useInfiniteQuery, @@ -72,7 +72,10 @@ export class DevupQueryClient> { path: T, ...options: [RequiredOptions] extends [never] ? [ - options?: DevupApiRequestInit, + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -80,7 +83,8 @@ export class DevupQueryClient> { queryClient?: Parameters>[1], ] : [ - options: DevupApiRequestInit & Omit, + options: Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -140,8 +144,13 @@ export class DevupQueryClient> { D extends ExtractValue, E extends ExtractValue, V extends [RequiredOptions] extends [never] - ? DevupApiRequestInit - : DevupApiRequestInit & Omit, + ? + | (IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit) + | undefined + : Omit & Omit, >( method: M, path: T, @@ -196,15 +205,15 @@ export class DevupQueryClient> { O extends Additional, D extends ExtractValue, E extends ExtractValue, - OP extends [RequiredOptions] extends [never] - ? DevupApiRequestInit | undefined - : DevupApiRequestInit & Omit, >( method: M, path: T, ...options: [RequiredOptions] extends [never] ? [ - options?: OP, + options?: IsCold extends true + ? DevupApiRequestInit + : Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -212,7 +221,8 @@ export class DevupQueryClient> { queryClient?: Parameters>[1], ] : [ - options: OP, + options: Omit & + Omit, queryOptions?: Omit< Parameters>[0], 'queryFn' | 'queryKey' @@ -244,12 +254,7 @@ export class DevupQueryClient> { } useInfiniteQuery< - T extends DevupApiStructKey, - O extends Additional>, - D extends ExtractValue, - E extends ExtractValue, - >( - method: + M extends | 'get' | 'post' | 'put' @@ -260,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 From c30cc1aee51f5831be6bfb2a25823716f8e4eb70 Mon Sep 17 00:00:00 2001 From: owjs3901 Date: Thu, 4 Dec 2025 22:17:01 +0900 Subject: [PATCH 4/4] Fix typing issue --- packages/react-query/src/create-query-client.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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>(