diff --git a/.changeset/neat-donkeys-pay.md b/.changeset/neat-donkeys-pay.md new file mode 100644 index 000000000..5f75bf300 --- /dev/null +++ b/.changeset/neat-donkeys-pay.md @@ -0,0 +1,5 @@ +--- +'@hey-api/openapi-ts': patch +--- + +fix: do not use a body serializer on text/plain sdks diff --git a/.changeset/six-horses-report.md b/.changeset/six-horses-report.md new file mode 100644 index 000000000..e5e017397 --- /dev/null +++ b/.changeset/six-horses-report.md @@ -0,0 +1,8 @@ +--- +'@hey-api/client-axios': patch +'@hey-api/client-fetch': patch +'@hey-api/client-nuxt': patch +'@hey-api/openapi-ts': patch +--- + +fix: add null to valid bodySerializer types diff --git a/examples/openapi-ts-sample/.gitignore b/examples/openapi-ts-sample/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/examples/openapi-ts-sample/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/openapi-ts-sample/index.html b/examples/openapi-ts-sample/index.html new file mode 100644 index 000000000..d301a3a91 --- /dev/null +++ b/examples/openapi-ts-sample/index.html @@ -0,0 +1,13 @@ + + + + + + + Hey API + Fetch API Demo + + +
+ + + diff --git a/examples/openapi-ts-sample/openapi-ts.config.ts b/examples/openapi-ts-sample/openapi-ts.config.ts new file mode 100644 index 000000000..2470f065a --- /dev/null +++ b/examples/openapi-ts-sample/openapi-ts.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from '@hey-api/openapi-ts'; + +export default defineConfig({ + client: '@hey-api/client-fetch', + input: + '../../packages/openapi-ts/test/spec/2.0.x/body-response-text-plain.yaml', + output: { + format: 'prettier', + lint: 'eslint', + path: './src/client', + }, + plugins: [ + '@hey-api/schemas', + '@hey-api/sdk', + { + enums: 'javascript', + name: '@hey-api/typescript', + }, + ], +}); diff --git a/examples/openapi-ts-sample/package.json b/examples/openapi-ts-sample/package.json new file mode 100644 index 000000000..9801d3ad7 --- /dev/null +++ b/examples/openapi-ts-sample/package.json @@ -0,0 +1,39 @@ +{ + "name": "@example/openapi-ts-sample", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "build": "tsc && vite build", + "dev": "vite", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "openapi-ts": "openapi-ts", + "preview": "vite preview", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@hey-api/client-fetch": "workspace:*", + "@radix-ui/react-form": "0.1.1", + "@radix-ui/react-icons": "1.3.2", + "@radix-ui/themes": "3.1.6", + "react": "19.0.0", + "react-dom": "19.0.0" + }, + "devDependencies": { + "@hey-api/openapi-ts": "workspace:*", + "@types/react": "19.0.1", + "@types/react-dom": "19.0.1", + "@typescript-eslint/eslint-plugin": "7.18.0", + "@typescript-eslint/parser": "7.15.0", + "@vitejs/plugin-react": "4.3.1", + "autoprefixer": "10.4.19", + "eslint": "9.17.0", + "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-refresh": "0.4.7", + "postcss": "8.4.39", + "prettier": "3.4.2", + "tailwindcss": "3.4.4", + "typescript": "5.5.3", + "vite": "6.0.7" + } +} diff --git a/examples/openapi-ts-sample/postcss.config.js b/examples/openapi-ts-sample/postcss.config.js new file mode 100644 index 000000000..9eef821c4 --- /dev/null +++ b/examples/openapi-ts-sample/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + autoprefixer: {}, + tailwindcss: {}, + }, +}; diff --git a/examples/openapi-ts-sample/src/App.css b/examples/openapi-ts-sample/src/App.css new file mode 100644 index 000000000..b5c61c956 --- /dev/null +++ b/examples/openapi-ts-sample/src/App.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/examples/openapi-ts-sample/src/App.tsx b/examples/openapi-ts-sample/src/App.tsx new file mode 100644 index 000000000..dbd10f3bb --- /dev/null +++ b/examples/openapi-ts-sample/src/App.tsx @@ -0,0 +1,40 @@ +import './App.css'; + +import { + Box, + Button, + Container, + Flex, + Heading, + Section, +} from '@radix-ui/themes'; + +import { postFoo } from './client/sdk.gen'; + +function App() { + const onClick = async () => { + postFoo({ + body: 'foo', + }); + }; + + return ( + + +
+ + sample for internal testing + +
+ + + +
+ + + ); +} + +export default App; diff --git a/examples/openapi-ts-sample/src/client/index.ts b/examples/openapi-ts-sample/src/client/index.ts new file mode 100644 index 000000000..688e3c912 --- /dev/null +++ b/examples/openapi-ts-sample/src/client/index.ts @@ -0,0 +1,3 @@ +// This file is auto-generated by @hey-api/openapi-ts +export * from './sdk.gen'; +export * from './types.gen'; diff --git a/examples/openapi-ts-sample/src/client/sdk.gen.ts b/examples/openapi-ts-sample/src/client/sdk.gen.ts new file mode 100644 index 000000000..eb9f289e4 --- /dev/null +++ b/examples/openapi-ts-sample/src/client/sdk.gen.ts @@ -0,0 +1,24 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { + createClient, + createConfig, + type Options, +} from '@hey-api/client-fetch'; + +import type { PostFooData, PostFooResponse } from './types.gen'; + +export const client = createClient(createConfig()); + +export const postFoo = ( + options: Options, +) => + (options?.client ?? client).post({ + bodySerializer: null, + url: '/foo', + ...options, + headers: { + 'Content-Type': 'text/plain', + ...options?.headers, + }, + }); diff --git a/examples/openapi-ts-sample/src/client/types.gen.ts b/examples/openapi-ts-sample/src/client/types.gen.ts new file mode 100644 index 000000000..bdb7d6bc0 --- /dev/null +++ b/examples/openapi-ts-sample/src/client/types.gen.ts @@ -0,0 +1,17 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type PostFooData = { + body: string; + path?: never; + query?: never; + url: '/foo'; +}; + +export type PostFooResponses = { + /** + * OK + */ + 200: string; +}; + +export type PostFooResponse = PostFooResponses[keyof PostFooResponses]; diff --git a/examples/openapi-ts-sample/src/main.tsx b/examples/openapi-ts-sample/src/main.tsx new file mode 100644 index 000000000..44ee3f3f4 --- /dev/null +++ b/examples/openapi-ts-sample/src/main.tsx @@ -0,0 +1,26 @@ +import '@radix-ui/themes/styles.css'; + +import { Theme } from '@radix-ui/themes'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; + +import App from './App.tsx'; +import { client } from './client/sdk.gen'; + +// configure internal service client +client.setConfig({ + // set default base url for requests + baseUrl: 'https://petstore3.swagger.io/api/v3', + // set default headers for requests + headers: { + Authorization: 'Bearer ', + }, +}); + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + , +); diff --git a/examples/openapi-ts-sample/src/vite-env.d.ts b/examples/openapi-ts-sample/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/examples/openapi-ts-sample/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/openapi-ts-sample/tailwind.config.js b/examples/openapi-ts-sample/tailwind.config.js new file mode 100644 index 000000000..0284c5614 --- /dev/null +++ b/examples/openapi-ts-sample/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{html,js,ts,jsx,tsx}'], + plugins: [], + theme: { + extend: {}, + }, +}; diff --git a/examples/openapi-ts-sample/tsconfig.json b/examples/openapi-ts-sample/tsconfig.json new file mode 100644 index 000000000..a7fc6fbf2 --- /dev/null +++ b/examples/openapi-ts-sample/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/examples/openapi-ts-sample/tsconfig.node.json b/examples/openapi-ts-sample/tsconfig.node.json new file mode 100644 index 000000000..97ede7ee6 --- /dev/null +++ b/examples/openapi-ts-sample/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/examples/openapi-ts-sample/vite.config.ts b/examples/openapi-ts-sample/vite.config.ts new file mode 100644 index 000000000..4e7004ebc --- /dev/null +++ b/examples/openapi-ts-sample/vite.config.ts @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/packages/client-axios/src/types.ts b/packages/client-axios/src/types.ts index 333e77d69..501a4a291 100644 --- a/packages/client-axios/src/types.ts +++ b/packages/client-axios/src/types.ts @@ -32,7 +32,7 @@ export interface Config * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer; + bodySerializer?: BodySerializer | null; /** * An object containing any HTTP headers that you want to pre-populate your * `Headers` object with. diff --git a/packages/client-fetch/src/types.ts b/packages/client-fetch/src/types.ts index d23859671..d48f7e59d 100644 --- a/packages/client-fetch/src/types.ts +++ b/packages/client-fetch/src/types.ts @@ -24,7 +24,7 @@ export interface Config * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer; + bodySerializer?: BodySerializer | null; /** * Fetch API implementation. You can use this option to provide a custom * fetch instance. diff --git a/packages/client-nuxt/src/types.ts b/packages/client-nuxt/src/types.ts index d866af3b3..0aff7480f 100644 --- a/packages/client-nuxt/src/types.ts +++ b/packages/client-nuxt/src/types.ts @@ -65,7 +65,7 @@ export interface Config * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer; + bodySerializer?: BodySerializer | null; /** * An object containing any HTTP headers that you want to pre-populate your * `Headers` object with. diff --git a/packages/openapi-ts/src/ir/__tests__/mediaType.test.ts b/packages/openapi-ts/src/ir/__tests__/mediaType.test.ts index de8395ad9..6d69c8c2a 100644 --- a/packages/openapi-ts/src/ir/__tests__/mediaType.test.ts +++ b/packages/openapi-ts/src/ir/__tests__/mediaType.test.ts @@ -1,70 +1,106 @@ import { describe, expect, it } from 'vitest'; -import { isMediaTypeFileLike } from '../mediaType'; +import type { IRMediaType } from '../mediaType'; +import { isMediaTypeFileLike, mediaTypeToIrMediaType } from '../mediaType'; describe('isMediaTypeFileLike', () => { const scenarios: Array<{ - fileLike: ReturnType; - mediaType: Parameters[0]['mediaType']; + mediaType: string; + response: boolean; }> = [ { - fileLike: false, mediaType: 'application/json', + response: false, }, { - fileLike: true, mediaType: 'application/json+download', + response: true, }, { - fileLike: false, mediaType: 'application/json; charset=ascii', + response: false, }, { - fileLike: true, mediaType: 'application/octet-stream', + response: true, }, { - fileLike: true, mediaType: 'application/pdf', + response: true, }, { - fileLike: true, mediaType: 'application/xml; charset=utf-8', + response: true, }, { - fileLike: true, mediaType: 'application/zip', + response: true, }, { - fileLike: false, mediaType: 'image/jpeg', + response: false, }, { - fileLike: false, mediaType: 'image/jpeg; charset=utf-8', + response: false, }, { - fileLike: false, mediaType: 'text/html; charset=utf-8', + response: false, }, { - fileLike: true, mediaType: 'text/javascript; charset=ISO-8859-1', + response: true, }, { - fileLike: false, mediaType: 'text/plain; charset=utf-8', + response: false, }, { - fileLike: true, mediaType: 'video/mp4', + response: true, }, ]; it.each(scenarios)( - 'detects $mediaType as file-like? $fileLike', - async ({ fileLike, mediaType }) => { - expect(isMediaTypeFileLike({ mediaType })).toEqual(fileLike); + 'detects $mediaType as file-like? $response', + async ({ mediaType, response }) => { + expect(isMediaTypeFileLike({ mediaType })).toEqual(response); + }, + ); +}); + +describe('mediaTypeToIrMediaType', () => { + const scenarios: Array<{ + mediaType: string; + response: IRMediaType | undefined; + }> = [ + { + mediaType: 'multipart/form-data', + response: 'form-data', + }, + { + mediaType: 'application/json', + response: 'json', + }, + { + mediaType: 'text/plain; charset=utf-8', + response: 'text', + }, + { + mediaType: 'application/x-www-form-urlencoded', + response: 'url-search-params', + }, + { + mediaType: 'application/foo', + response: undefined, + }, + ]; + + it.each(scenarios)( + 'ir media type for $mediaType: $response', + async ({ mediaType, response }) => { + expect(mediaTypeToIrMediaType({ mediaType })).toEqual(response); }, ); }); diff --git a/packages/openapi-ts/src/ir/mediaType.ts b/packages/openapi-ts/src/ir/mediaType.ts index 6883cfa38..0db232aaa 100644 --- a/packages/openapi-ts/src/ir/mediaType.ts +++ b/packages/openapi-ts/src/ir/mediaType.ts @@ -2,10 +2,11 @@ const fileLikeRegExp = /^(application\/(pdf|rtf|msword|vnd\.(ms-|openxmlformats-officedocument\.)|zip|x-(7z|tar|rar|zip|iso)|octet-stream|gzip|x-msdownload|json\+download|xml|x-yaml|x-7z-compressed|x-tar)|text\/(yaml|css|javascript)|audio\/(mpeg|wav)|video\/(mp4|x-matroska)|image\/(vnd\.adobe\.photoshop|svg\+xml))(; ?charset=[^;]+)?$/i; const jsonMimeRegExp = /^application\/(.*\+)?json(;.*)?$/i; const multipartFormDataMimeRegExp = /^multipart\/form-data(;.*)?$/i; +const textMimeRegExp = /^text\/[a-z0-9.+-]+(;.*)?$/i; const xWwwFormUrlEncodedMimeRegExp = /^application\/x-www-form-urlencoded(;.*)?$/i; -export type IRMediaType = 'form-data' | 'json' | 'url-search-params'; +export type IRMediaType = 'form-data' | 'json' | 'text' | 'url-search-params'; export const isMediaTypeFileLike = ({ mediaType, @@ -31,6 +32,11 @@ export const mediaTypeToIrMediaType = ({ return 'form-data'; } + textMimeRegExp.lastIndex = 0; + if (textMimeRegExp.test(mediaType)) { + return 'text'; + } + xWwwFormUrlEncodedMimeRegExp.lastIndex = 0; if (xWwwFormUrlEncodedMimeRegExp.test(mediaType)) { return 'url-search-params'; diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts index 8d1bdfa2b..85b46f40f 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/plugin.ts @@ -254,6 +254,14 @@ const operationStatements = ({ }); break; case 'json': + // jsonBodySerializer is the default, no need to specify + break; + case 'text': + // ensure we don't use any serializer by default + requestOptions.push({ + key: 'bodySerializer', + value: null, + }); break; case 'url-search-params': requestOptions.push({ spread: 'urlSearchParamsBodySerializer' }); diff --git a/packages/openapi-ts/test/2.0.x.test.ts b/packages/openapi-ts/test/2.0.x.test.ts index 66fedebff..f67970fa9 100644 --- a/packages/openapi-ts/test/2.0.x.test.ts +++ b/packages/openapi-ts/test/2.0.x.test.ts @@ -38,6 +38,7 @@ describe(`OpenAPI ${version}`, () => { config: createConfig({ input: 'body-response-text-plain.yaml', output: 'body-response-text-plain', + plugins: ['@hey-api/typescript', '@hey-api/sdk'], }), description: 'handle text/plain content type', }, diff --git a/packages/openapi-ts/test/3.0.x.test.ts b/packages/openapi-ts/test/3.0.x.test.ts index 245525960..6a772738f 100644 --- a/packages/openapi-ts/test/3.0.x.test.ts +++ b/packages/openapi-ts/test/3.0.x.test.ts @@ -67,6 +67,7 @@ describe(`OpenAPI ${version}`, () => { config: createConfig({ input: 'body-response-text-plain.yaml', output: 'body-response-text-plain', + plugins: ['@hey-api/typescript', '@hey-api/sdk'], }), description: 'handle text/plain content type', }, diff --git a/packages/openapi-ts/test/3.1.x.test.ts b/packages/openapi-ts/test/3.1.x.test.ts index 63adc6454..1dae4f653 100644 --- a/packages/openapi-ts/test/3.1.x.test.ts +++ b/packages/openapi-ts/test/3.1.x.test.ts @@ -67,6 +67,7 @@ describe(`OpenAPI ${version}`, () => { config: createConfig({ input: 'body-response-text-plain.yaml', output: 'body-response-text-plain', + plugins: ['@hey-api/typescript', '@hey-api/sdk'], }), description: 'handle text/plain content type', }, diff --git a/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/index.ts b/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/index.ts index 56bade120..e64537d21 100644 --- a/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/index.ts +++ b/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/index.ts @@ -1,2 +1,3 @@ // This file is auto-generated by @hey-api/openapi-ts -export * from './types.gen'; \ No newline at end of file +export * from './types.gen'; +export * from './sdk.gen'; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts b/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts new file mode 100644 index 000000000..e8ec14a9a --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/2.0.x/body-response-text-plain/sdk.gen.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createClient, createConfig, type Options } from '@hey-api/client-fetch'; +import type { PostFooData, PostFooResponse } from './types.gen'; + +export const client = createClient(createConfig()); + +export const postFoo = (options: Options) => { + return (options?.client ?? client).post({ + bodySerializer: null, + url: '/foo', + ...options, + headers: { + 'Content-Type': 'text/plain', + ...options?.headers + } + }); +}; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/index.ts b/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/index.ts index 56bade120..e64537d21 100644 --- a/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/index.ts +++ b/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/index.ts @@ -1,2 +1,3 @@ // This file is auto-generated by @hey-api/openapi-ts -export * from './types.gen'; \ No newline at end of file +export * from './types.gen'; +export * from './sdk.gen'; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts b/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts new file mode 100644 index 000000000..e8ec14a9a --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/3.0.x/body-response-text-plain/sdk.gen.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createClient, createConfig, type Options } from '@hey-api/client-fetch'; +import type { PostFooData, PostFooResponse } from './types.gen'; + +export const client = createClient(createConfig()); + +export const postFoo = (options: Options) => { + return (options?.client ?? client).post({ + bodySerializer: null, + url: '/foo', + ...options, + headers: { + 'Content-Type': 'text/plain', + ...options?.headers + } + }); +}; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/index.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/index.ts index 56bade120..e64537d21 100644 --- a/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/index.ts +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/index.ts @@ -1,2 +1,3 @@ // This file is auto-generated by @hey-api/openapi-ts -export * from './types.gen'; \ No newline at end of file +export * from './types.gen'; +export * from './sdk.gen'; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/sdk.gen.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/sdk.gen.ts new file mode 100644 index 000000000..e8ec14a9a --- /dev/null +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/body-response-text-plain/sdk.gen.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createClient, createConfig, type Options } from '@hey-api/client-fetch'; +import type { PostFooData, PostFooResponse } from './types.gen'; + +export const client = createClient(createConfig()); + +export const postFoo = (options: Options) => { + return (options?.client ?? client).post({ + bodySerializer: null, + url: '/foo', + ...options, + headers: { + 'Content-Type': 'text/plain', + ...options?.headers + } + }); +}; \ No newline at end of file diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-axios/bundle/client/types.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-axios/bundle/client/types.ts index 333e77d69..501a4a291 100644 --- a/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-axios/bundle/client/types.ts +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-axios/bundle/client/types.ts @@ -32,7 +32,7 @@ export interface Config * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer; + bodySerializer?: BodySerializer | null; /** * An object containing any HTTP headers that you want to pre-populate your * `Headers` object with. diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-fetch/bundle/client/types.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-fetch/bundle/client/types.ts index d23859671..d48f7e59d 100644 --- a/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-fetch/bundle/client/types.ts +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-fetch/bundle/client/types.ts @@ -24,7 +24,7 @@ export interface Config * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer; + bodySerializer?: BodySerializer | null; /** * Fetch API implementation. You can use this option to provide a custom * fetch instance. diff --git a/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-nuxt/bundle/client/types.ts b/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-nuxt/bundle/client/types.ts index d866af3b3..0aff7480f 100644 --- a/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-nuxt/bundle/client/types.ts +++ b/packages/openapi-ts/test/__snapshots__/3.1.x/clients/@hey-api/client-nuxt/bundle/client/types.ts @@ -65,7 +65,7 @@ export interface Config * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer; + bodySerializer?: BodySerializer | null; /** * An object containing any HTTP headers that you want to pre-populate your * `Headers` object with. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f84f77f9..dc8aa5592 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -275,6 +275,73 @@ importers: specifier: workspace:* version: link:../../packages/openapi-ts + examples/openapi-ts-sample: + dependencies: + '@hey-api/client-fetch': + specifier: workspace:* + version: link:../../packages/client-fetch + '@radix-ui/react-form': + specifier: 0.1.1 + version: 0.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-icons': + specifier: 1.3.2 + version: 1.3.2(react@19.0.0) + '@radix-ui/themes': + specifier: 3.1.6 + version: 3.1.6(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: + specifier: 19.0.0 + version: 19.0.0 + react-dom: + specifier: 19.0.0 + version: 19.0.0(react@19.0.0) + devDependencies: + '@hey-api/openapi-ts': + specifier: workspace:* + version: link:../../packages/openapi-ts + '@types/react': + specifier: 19.0.1 + version: 19.0.1 + '@types/react-dom': + specifier: 19.0.1 + version: 19.0.1 + '@typescript-eslint/eslint-plugin': + specifier: 7.18.0 + version: 7.18.0(@typescript-eslint/parser@7.15.0(eslint@9.17.0(jiti@2.4.2))(typescript@5.5.3))(eslint@9.17.0(jiti@2.4.2))(typescript@5.5.3) + '@typescript-eslint/parser': + specifier: 7.15.0 + version: 7.15.0(eslint@9.17.0(jiti@2.4.2))(typescript@5.5.3) + '@vitejs/plugin-react': + specifier: 4.3.1 + version: 4.3.1(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.0)(sass@1.80.7)(terser@5.36.0)(yaml@2.7.0)) + autoprefixer: + specifier: 10.4.19 + version: 10.4.19(postcss@8.4.39) + eslint: + specifier: 9.17.0 + version: 9.17.0(jiti@2.4.2) + eslint-plugin-react-hooks: + specifier: 4.6.2 + version: 4.6.2(eslint@9.17.0(jiti@2.4.2)) + eslint-plugin-react-refresh: + specifier: 0.4.7 + version: 0.4.7(eslint@9.17.0(jiti@2.4.2)) + postcss: + specifier: 8.4.39 + version: 8.4.39 + prettier: + specifier: 3.4.2 + version: 3.4.2 + tailwindcss: + specifier: 3.4.4 + version: 3.4.4(ts-node@10.9.2(@types/node@22.10.5)(typescript@5.5.3)) + typescript: + specifier: 5.5.3 + version: 5.5.3 + vite: + specifier: 6.0.7 + version: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(less@4.2.0)(sass@1.80.7)(terser@5.36.0)(yaml@2.7.0) + examples/openapi-ts-tanstack-angular-query-experimental: dependencies: '@angular/animations':