Node.js library that generates React Hooks based on the OpenAPI specification.
This project is a fork of openapi-typescript-codegen, which:
- Generates React hooks for OpenAPI specification, which is driven by jotai;
- Fixed many bugs in the schema generator, which could help us generate ajv-compliant JSON Schema;
- Add client side type validation to enhance the robostness of your website;
- Dropped the support of OpenAPI v2 and XHR mode.
npm install @jbcz/openapi-hooks-codegen --save-dev Notice: React Native users may need react-native-url-polyfill to get the support of baseUrl configuration, please checkout the documentation.
$ openapi --help Usage: openapi [options] Options: -V, --version output the version number -i, --input <value> OpenAPI specification, can be a path, url or string content (required) -o, --output <value> Output directory (required) Examples $ openapi --input ./spec.json $ openapi --input ./spec.json --output ./dist package.json
{ "scripts": { "generate": "openapi --input ./spec.json --output ./dist" } }Node.js API
const OpenAPI = require('openapi-hooks-codegen'); OpenAPI.generate({ input: './spec.json', output: './dist' }); // Or by providing the content of the spec directly π OpenAPI.generate({ input: require('./spec.json'), output: './dist' });Basic usage
import { useGetRole } from './api'; const [role, roleController] = useGetRole(); roleController.fetchData(1);Side effect
Like setting localStorage after a login request.
import { useGetRole } from './api'; const [role, roleController] = useGetRole(); roleController.fetchData(1, {}, (atom, set, result) => { set({ ...atom, data: result.body }); localStorage.setItem('token', result.body); });Credential
import { useGetRole, globalOptionsAtom } from './api'; const [role, roleController] = useGetRole(); const [globalConfig, setGlobalConfig] = useAtom(globalOptionsAtom) setGlobalConfig({ headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, }, }); roleController.fetchData(1);Request body of a post request
import { useCreateRole } from './api'; const [role, createRoleController] = useCreateRole(); createRoleController.fetchData({ name: 'xxx', permissions: ['xxx'], // ... });Request header of a request
import { useGetRole } from './api'; const [role, roleController] = useGetRole(); roleController.fetchData(1, { headers: { 'YourHeader': `YourValue`, // ... }, });Infinite scrolling
import { useGetRole } from './api'; const [role, roleController] = useGetRole(); roleController.fetchData(1, {}, (atom, set, result) => { set({ ...atom, data: atom.data.concat(result), }) });If your team is using Gitea and want to automatically sync the spec with the repository, you can use the following project setup:
- Installing some dependencies:
yarn add -D npm-run-all dotenv-cli @jbcz/openapi-hooks-codegen - Creating a
.env.openapifile in the root directory of your project, with the following content:
GITEA_TOKEN=YOUR_SUPER_SECRET_TOKEN - Adding the following configuration to the
scriptssection of yourpackage.jsonfile:
"scripts": { "sync-spec": "dotenv-cli -e /env.openapi openapi-sync-gitea --ref RELEASE_TAG --owner REPO_OWNER --repo REPO_ID --filePath FILE_PATH_IN_THE_REPO --host GITEA_HOST -o ./spec.yaml", "gen-api": "openapi --input ./spec.yaml ./src/api/", "postinstall": "npm-run-all sync-spec gen-api", }, -
Creating a
.gitkeepfile in the./src/api/. -
IMPORTANT: Add the following configuration to your
.gitignorefile:
/env.openapi /spec.yaml /src/api/ !/src/api/.gitkeep - Edit
tsconfig.jsonto add the following configuration:
{ "compilerOptions": { "baseUrl": "src", } } - Run
yarn postinstallto generate the API.
If you use enums inside your models / definitions then those enums are by default inside a namespace with the same name as your model. This is called declaration merging. However, the @babel/plugin-transform-typescript does not support these namespaces, so if you are using babel in your project please use the --useUnionTypes flag to generate union types instead of traditional enums. More info can be found here: Enums vs. Union Types.
Note: If you are using Babel 7 and Typescript 3.8 (or higher) then you should enable the onlyRemoveTypeImports to ignore any 'type only' imports, see https://babeljs.io/docs/en/babel-preset-typescript#onlyremovetypeimports for more info
module.exports = { presets: [ ['@babel/preset-typescript', { onlyRemoveTypeImports: true, }], ], };