Open7
hey-api
openapi-ts.config
import {defineConfig} from '@hey-api/openapi-ts';
export default defineConfig({
client: '@hey-api/client-axios',
input: 'http://localhost:8000/openapi.json',
output: 'src/client',
types: {
enums: false,
},
services: {
asClass: true,
}
});
Nextjs SSR CSR
axiosのインターセプターをapp routerで適切に設定するにはSSRのレイアウトの中でCSRのコンポーネントを定義してGlobalConfigとして設定する方法がベター?
import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
import "@fontsource/material-icons";
import {ReactNode} from "react";
import {SITE_NAME, SiteMetaConst} from "@/constants/SiteMetaConst";
import ClientGlobalConfig from "@/components/Layout/ClientGlobalConfig";
export const metadata = SiteMetaConst;
const RootLayout = ({children}: { children: ReactNode }) => {
return (
<html lang="en">
<head>
<title>{SITE_NAME}</title>
</head>
<body>
<ClientGlobalConfig/>
{children}
</body>
</html>
);
};
export default RootLayout;
'use client'
import {FC} from "react";
import axios, {AxiosError} from "axios";
import {client} from "@hey-api/client-axios";
client.instance.interceptors.response.use(
(res) => {
return res
},
async (error: AxiosError) => {
if (
error.config &&
error.response?.status === 401 &&
// @ts-ignore
error.response.data.detail === "Token expired" &&
(error.config.retryCount ?? 0) < 3 &&
!error.config.url?.endsWith("/api/auth/refresh-token")
) {
// eslint-disable-next-line no-param-reassign
error.config.retryCount = 1 + (error.config.retryCount ?? 0);
try {
await axios.get("/api/auth/refresh-token", {
responseType: "json",
withCredentials: true,
headers: {
"Content-Type": "application/json",
},
});
return await axios(error.config);
} catch (e) {
if (typeof window !== "undefined") {
const currentUrl = new URL(window.location.href);
const pathSegments = currentUrl.pathname.split("/");
const lang = pathSegments[1];
window.location.href = `/${lang}/auth/signin?redirect=${encodeURIComponent(
currentUrl.toString(),
)}`;
}
return Promise.reject(e);
}
}
return Promise.reject(error);
},
);
const ClientGlobalConfig: FC = () => {
return <div/>
}
export default ClientGlobalConfig;
Axios client does not throw exeption
Config Axios
Migration
before
import { defineConfig } from '@hey-api/openapi-ts';
function makeMethodNameFromSummary(str: string): string {
return str
.split(' ')
.map((word, index) => {
if (index === 0) {
return word.toLowerCase();
} else {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
})
.join('');
}
export default defineConfig({
client: '@hey-api/client-axios',
input: 'http://localhost:8000/openapi.json',
output: 'src/client',
types: {
enums: false,
},
services: {
asClass: true,
methodNameBuilder: (operation) => {
if (operation.summary) {
return makeMethodNameFromSummary(operation.summary);
}
console.warn('Operation summary is not defined:', operation.name);
return operation.name;
},
},
});
after
import { defaultPlugins, defineConfig } from '@hey-api/openapi-ts';
function makeMethodNameFromSummary(str: string): string {
return str
.split(' ')
.map((word, index) => {
if (index === 0) {
return word.toLowerCase();
} else {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
})
.join('');
}
export default defineConfig({
client: '@hey-api/client-fetch',
experimentalParser: true,
input: 'http://localhost:8000/openapi.json',
output: 'src/lib/client',
plugins: [
...defaultPlugins,
{
enums: false,
name: '@hey-api/typescript'
},
{
asClass: true,
name: '@hey-api/sdk',
methodNameBuilder: (operation) => {
if (operation.summary) {
return makeMethodNameFromSummary(operation.summary);
}
console.warn('Operation summary is not defined:', operation.id);
return operation.id || 'unknown';
}
}
]
});
fetch config to throw error on status
import { createConfig } from '@hey-api/client-fetch';
const config = createConfig({
throwOnError: true
});
client.setConfig(config);