Skip to content

Commit 7f3308a

Browse files
authored
Merge pull request #2483 from hey-api/chore/sdk-openai
chore: add OpenAI spec
2 parents df9b830 + f17de4c commit 7f3308a

29 files changed

+83744
-291
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Hey API + OpenAI Demo</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import path from 'node:path';
2+
3+
import { defineConfig } from '@hey-api/openapi-ts';
4+
5+
export default defineConfig({
6+
input: path.resolve(
7+
'..',
8+
'..',
9+
'packages',
10+
'openapi-ts-tests',
11+
'specs',
12+
'3.1.x',
13+
'openai.yaml',
14+
),
15+
output: {
16+
format: 'prettier',
17+
lint: 'eslint',
18+
path: './src/client',
19+
},
20+
plugins: [
21+
'@hey-api/client-fetch',
22+
{
23+
enums: 'javascript',
24+
name: '@hey-api/typescript',
25+
},
26+
{
27+
instance: 'OpenAI',
28+
name: '@hey-api/sdk',
29+
},
30+
],
31+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "@example/openapi-ts-openai",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"build": "tsc && vite build",
8+
"dev": "vite",
9+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10+
"openapi-ts": "openapi-ts",
11+
"preview": "vite preview",
12+
"typecheck": "tsc --noEmit"
13+
},
14+
"dependencies": {
15+
"@radix-ui/react-form": "0.1.1",
16+
"@radix-ui/react-icons": "1.3.2",
17+
"@radix-ui/themes": "3.1.6",
18+
"openai": "5.13.1",
19+
"react": "19.0.0",
20+
"react-dom": "19.0.0"
21+
},
22+
"devDependencies": {
23+
"@config/vite-base": "workspace:*",
24+
"@hey-api/openapi-ts": "workspace:*",
25+
"@types/react": "19.0.1",
26+
"@types/react-dom": "19.0.1",
27+
"@typescript-eslint/eslint-plugin": "8.29.1",
28+
"@typescript-eslint/parser": "8.29.1",
29+
"@vitejs/plugin-react": "4.4.0-beta.1",
30+
"autoprefixer": "10.4.19",
31+
"eslint": "9.17.0",
32+
"eslint-plugin-react-hooks": "5.2.0",
33+
"eslint-plugin-react-refresh": "0.4.7",
34+
"postcss": "8.4.41",
35+
"prettier": "3.4.2",
36+
"tailwindcss": "3.4.9",
37+
"typescript": "5.8.3",
38+
"vite": "7.1.2"
39+
}
40+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
plugins: {
3+
autoprefixer: {},
4+
tailwindcss: {},
5+
},
6+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import './App.css';
2+
3+
import * as Form from '@radix-ui/react-form';
4+
import { PlusIcon } from '@radix-ui/react-icons';
5+
import {
6+
Box,
7+
Button,
8+
Container,
9+
Flex,
10+
Heading,
11+
Section,
12+
TextField,
13+
} from '@radix-ui/themes';
14+
import OpenAI from 'openai';
15+
import { useState } from 'react';
16+
17+
import { client as baseClient } from './client/client.gen';
18+
import { OpenAi } from './client/sdk.gen';
19+
20+
const sdk = new OpenAI({
21+
apiKey: import.meta.env.VITE_OPENAI_API_KEY,
22+
dangerouslyAllowBrowser: true,
23+
});
24+
25+
baseClient.setConfig({
26+
auth() {
27+
return import.meta.env.VITE_OPENAI_API_KEY;
28+
},
29+
});
30+
31+
const client = new OpenAi({
32+
client: baseClient,
33+
});
34+
35+
function App() {
36+
const [isRequiredNameError] = useState(false);
37+
38+
const onCreateResponse = async (values: FormData) => {
39+
const response = await sdk.responses.create({
40+
input: values.get('input') as string,
41+
model: 'gpt-5-nano',
42+
});
43+
44+
console.log(response.output_text);
45+
const { data, error } = await client.createResponse({
46+
body: {
47+
input: values.get('input') as string,
48+
model: 'gpt-5-nano',
49+
},
50+
});
51+
if (error) {
52+
console.log(error);
53+
return;
54+
}
55+
console.log(data?.output);
56+
};
57+
58+
return (
59+
<Box
60+
style={{ background: 'var(--gray-a2)', borderRadius: 'var(--radius-3)' }}
61+
>
62+
<Container size="1">
63+
<Section size="1" />
64+
<Flex align="center">
65+
<a className="shrink-0" href="https://heyapi.dev/" target="_blank">
66+
<img
67+
src="https://heyapi.dev/logo.png"
68+
className="h-16 w-16 transition duration-300 will-change-auto"
69+
alt="Hey API logo"
70+
/>
71+
</a>
72+
<Heading>@hey-api/openapi-ts 🤝 OpenAI</Heading>
73+
</Flex>
74+
<Section size="1" />
75+
<Flex direction="column" gapY="2">
76+
<Form.Root
77+
className="w-[400px]"
78+
onSubmit={(event) => {
79+
event.preventDefault();
80+
onCreateResponse(new FormData(event.currentTarget));
81+
}}
82+
>
83+
<Form.Field className="grid mb-[10px]" name="input">
84+
<div className="flex items-baseline justify-between">
85+
<Form.Label className="text-[15px] font-medium leading-[35px] text-white">
86+
Input
87+
</Form.Label>
88+
{isRequiredNameError && (
89+
<Form.Message className="text-[13px] text-white opacity-[0.8]">
90+
Please enter a name
91+
</Form.Message>
92+
)}
93+
<Form.Message
94+
className="text-[13px] text-white opacity-[0.8]"
95+
match="valueMissing"
96+
>
97+
Please enter an input
98+
</Form.Message>
99+
</div>
100+
<Form.Control asChild>
101+
<TextField.Root
102+
placeholder="Write a one-sentence bedtime story about a unicorn."
103+
name="input"
104+
type="text"
105+
required
106+
/>
107+
</Form.Control>
108+
</Form.Field>
109+
<Flex gapX="2">
110+
<Form.Submit asChild>
111+
<Button type="submit">
112+
<PlusIcon /> Create Response
113+
</Button>
114+
</Form.Submit>
115+
{/* <Button onClick={onUpdatePet} type="button">
116+
<ReloadIcon /> Update Pet
117+
</Button> */}
118+
</Flex>
119+
</Form.Root>
120+
</Flex>
121+
<Section size="1" />
122+
</Container>
123+
</Box>
124+
);
125+
}
126+
127+
export default App;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This file is auto-generated by @hey-api/openapi-ts
2+
3+
import {
4+
type ClientOptions as DefaultClientOptions,
5+
type Config,
6+
createClient,
7+
createConfig,
8+
} from './client';
9+
import type { ClientOptions } from './types.gen';
10+
11+
/**
12+
* The `createClientConfig()` function will be called on client initialization
13+
* and the returned object will become the client's initial configuration.
14+
*
15+
* You may want to initialize your client this way instead of calling
16+
* `setConfig()`. This is useful for example if you're using Next.js
17+
* to ensure your client always has the correct values.
18+
*/
19+
export type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> =
20+
(
21+
override?: Config<DefaultClientOptions & T>,
22+
) => Config<Required<DefaultClientOptions> & T>;
23+
24+
export const client = createClient(
25+
createConfig<ClientOptions>({
26+
baseUrl: 'https://api.openai.com/v1',
27+
}),
28+
);

0 commit comments

Comments
 (0)