OpenAPI Generator + TypeScript ã§å§ããèªåçæã®åã«å®ãããè±ããªã¯ã©ã¤ã¢ã³ãçæ´»
2020.02.29
OpenAPIãããã¥ã¡ã³ãã ãã§ãªããSchema firstãªéçºã«å©ç¨ãããã¨ãããã¨ã§ãTypeScript + OpenAPI Generatorã§ããã³ãã¨ã³ãã®éçºããã¾ããã Vue, Nuxtã§ä½¿ãéã®ä¾ã¨å ±ã«ãã®å 容ãç´¹ä»ãã¾ãã
ç®æ¬¡
- OpenAPIã§ããã¥ã¡ã³ããæ¸ãã¡ãªãããªã©
- OpenAPI Generatorã§Clientæ å ±ãåãåºã
- Vue, Nuxtã§å©ç¨ãã
- APIã®å¤æ´ã«è¿½å¾ãããããåãããã幸ã
OpenAPIã§ããã¥ã¡ã³ããæ¸ãã¡ãªãããªã©
å¼ç¤¾ã§ã¯ä»¥ä¸ã®ããã°ã§ãæ¸ãã¦ããããã«ãAPIä»æ§ã®ããã¥ã¡ã³ãåã«OpenAPIãæ´»ç¨ãã¦ãã¾ãã
- committeeÃOpenAPIÃRailsã§ã¹ãã¼ããã¡ã¼ã¹ããªAPIéçº
- OpenAPIã®ã¹ãã¼ããåå²ã»æ§é åãã¦ããæ¹æ³
ããã³ãã¨ã³ãã¨ããã¯ã¨ã³ãã§å®è£
ãã人ãç°ãªãå ´åãã¾ããå°æ¥çã«ç°ãªã人ãå®è£
ããå¯è½æ§ãããå ´åããåç´ã«è¦ãããããã¥ã¡ã³ãä½ãã¨ããç¹ã§èãã¦ããOpenAPIãå©ç¨ããã¡ãªããã¯å¤§ããã¨æãã¦ããã¾ãã
ããã¦ããã®ã¡ãªãããæ¡å¤§ãã¦ããããªã¨æãã¦ããã®ããOpenAPI Generatorãå©ç¨ããéçºã§ãã
å¼ç¤¾ã§ã¯ããã³ãã¨ã³ãã®å®è£
ã¯Nuxt.js + TypeScriptãå©ç¨ãããã¨ãå¤ãã®ã§ãããããã§axiosãªã©ãå©ç¨ãã¦APIããªã¯ã¨ã¹ãããé¨åãªã©ã«OpenAPI Generatorã§åãåºããåãå©ç¨ããã¨ã
- åã«é¢ãããã¡ã¤ã«ãèªåã§æ¸ããªãã¦æ¸ã
- èªåã§æ¸ããªãã®ã§ééããçºçãã«ããï¼å ã ã®ãã¡ã¤ã«ãééã£ã¦ããããã¡ãªãã§ããï¼
- APIã®ä¿®æ£ã«è¿½å¾ãããã
ãªã©ã®ã¡ãªãããå¢ãã¾ããã
ä»åã¯OpenAPI Generatorã®Vue.js, Nuxt.jsã¸ã®å°å
¥æ¹æ³ãªã©ããç´¹ä»ãããã¨æãã¾ãã
1. OpenAPI Generatorã§Clientæ å ±ãåãåºã
1.1 packageã®ã¤ã³ã¹ãã¼ã«
yarnãbrewã§globalã«installããæ¹æ³ãããã®ã§ãããCIãªã©ã§ãã§ãã¯ããå ´åã«ã使ãããã®ã§ãç§ã¯yarnã§projectãã¨ã«openapi-generatorãinstallãã¦ãã¾ãã
$ yarn add -D @openapitools/openapi-generator-cli
or
$ npm install @openapitools/openapi-generator-cli -D
1.2 package.jsonã®scriptsã«è¿½è¨
Clientãçæããscript generate-client
ãªã©ã追è¨ãã¾ãã
openapi-generator generate -g typescript-axios
-g
ã§å©ç¨ããGeneratorãé¸æãã¾ãã
ä»å㯠typescript-axios
ãå©ç¨ãã¦ãã¾ãããå©ç¨ããè¨èªã»ãã¬ã¼ã ã¯ã¼ã¯ã«ãã£ã¦å¤æ´å¯è½ã§ããï¼åè *2ï¼
<å°ãã¿>check-yml
format-yml
validate-schema
ãªã©ãåããã¦è¨è¿°ãã¦ãã¾ããã
prettierãå©ç¨ããyamlã®ãã©ã¼ããããã§ãã¯ãgeneratorã®validateã¯CIã§ãã§ãã¯ããéã«ä¾¿å©ãªã®ã§ããããã§ãð
{
"name": "Application-Name",
"version": "1.0.0",
"private": true,
"scripts": {
"check-yml": "prettier --check './path/to/openapi.yaml'",
"format-yml": "prettier --write './path/to/openapi.yaml'",
"validate-schema": "openapi-generator validate -i ./path/to/openapi.yaml",
"generate-client": "openapi-generator generate -g typescript-axios -i ./path/to/openapi.yaml -o ./frontoend-application-directory/src/types/typescript-axios",
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^1.0.10-4.2.3",
}
}
1.3 Clientã®çæ
å ã»ã©ç»é²ããscriptã§clientãçæãã¾ãã
$ yarn generate-client
çæå¾ã®ã½ã¼ã¹ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
ããã§Clientçæã¾ã§ã¯å®äºã§æºåãçµãã£ãç¶æ
ã§ãã
$ tree -L 2 ./types
./types
âââ client-axios
â  âââ api.ts
â  âââ base.ts
â  âââ configuration.ts
â  âââ git_push.sh
â  âââ index.ts
âââ index.d.ts
2. Vue, Nuxtã§å©ç¨ãã
ããããã¯å
ã»ã©çæããClientãã©ã®ããã«å©ç¨ãã¦ãããã®è©±ãã§ãã
çæãããåæ
å ±ãªã©ããã©ã®ããã«ä½¿ã£ã¦ããã®ãããã°ã¤ã³ç»é¢ã®ã½ã¼ã¹ããã¼ã¹ã«èª¬æãã¾ãã
2.1 Yamlã¨çæãããclient
以ä¸ã¯ api.ts ã«å«ã¾ãã ãã°ã¤ã³æã«å¿
è¦ãª loginId, passwordã®æ
å ±ã§ãã
ãã¨ãã¨ã®OpenAPIã®æ
å ±ãè¨è¿°ãããyamlã®å
容ãgenerateãã㨠api.ts
ã®å
容ãçæããã¾ãã
openapi.yaml
ããLoginRequesté¨åãæç²ã
LoginRequest:
title: LoginRequest
type: object
description: èªè¨¼æ
å ±
required: [loginId, password]
properties:
loginId:
type: string
description: ãã°ã¤ã³ID
password:
type: string
description: ãã¹ã¯ã¼ã
ãã¡ã¤ã«ï¼ ./types/typescript-client/api.ts
/**
* èªè¨¼æ
å ±
* @export
* @interface LoginRequest
*/
export interface LoginRequest {
/**
* ãã°ã¤ã³ID
* @type {string}
* @memberof Auth
*/
loginId: string;
/**
* ãã¹ã¯ã¼ã
* @type {string}
* @memberof Auth
*/
password: string;
}
2.2 çæãããClientãVueããå©ç¨ãã
ä¸ã§çæãããClientæ
å ±ããlogin.vueã§èªã¿è¾¼ã¿ã¾ãã
data ã® interfaceã§çæãããåã®æ
å ±ãå©ç¨ãã¦ãã¾ãã
æ®æ®µã ã¨ãã®æ
å ±ãèªåã§è¨è¿°ããå¿
è¦ãããã¨æãã¾ããã
çæãããå
容ãå©ç¨ããã ãã«ãªãã®ã§æ¥½ãã§ãã¾ããð¤
ãã¡ã¤ã«ï¼ ./pages/login.vue
import Vue from 'vue'
import Cookies from 'universal-cookie'
import { LoginRequest } from '@/types/typescript-axios'
interface Data {
value: LoginRequest,
}
export default Vue.extend({
components: {
},
data: (): Data => {
return {
value: {
loginId: '',
password: '',
},
}
},
methods: {
async login() {
try {
await this.$store.dispatch('auth/login', {
basePath: process.env.VUE_APP_BASE_PATH, // APIã®URL
value: this.value,
cookie: new Cookies(),
stage: process.env.VUE_APP_STAGE, // localã§cookieã«Secureå±æ§ãã¤ããªãããããããã«æ¸¡ãã¦ããã ãã§ãï¼ä¸è¦ãªæ¹ã¯æ¶ãã¦OKï¼
})
} catch (error) {
// ã¨ã©ã¼ããããªã«
}
},
},
})
2.3 çæãããClientãstore(Vuex)ã§å©ç¨ãã
login.vue
ã® loginã¡ã½ããã§å¼ã°ãã¦ããstore/authã®å
容ã§ãã
ãã¡ãã§ã¯ã LoginRequest
ã®åæ
å ±ã«å ãã¦ã AuthApi
ã®classãimportãã¾ãã
storeã®ä¸ã§ãããå©ç¨ãã¦APIã¸ã®ãªã¯ã¨ã¹ããè¡ã£ã¦ãã¾ãã
çæããã AuthApi
ã®æ¹ã§axiosãå©ç¨ãã¦ãªã¯ã¨ã¹ãããé¨åãè¨è¿°ãã¦ãããããstoreã§ã¯ã¨ã³ããã¤ã³ãã«å¯¾å¿ããã¡ã½ãããå¼ãã§ããã ãã«ãªãã¾ãï¼ä¾¿å©ãã¤ã³ãã§ããï¼ï¼
AuthApi({ basePath: params.basePath })
ã¨ãAPIã®URLã渡ãã¦ãã¾ãããèªè¨¼ãæ±ããããã¨ã³ããã¤ã³ããªã©ã¯ä»¥ä¸ã®ããã«tokenã渡ãã¦ããã¨ããªã¯ã¨ã¹ãæã« Bearer
ãªã©æå®ã®èªè¨¼æ¹æ³ã«å¿ãã¦Headerã«è¿½å ãã¦ããã¾ãã
new MeApi({
basePath: params.basePath,
accessToken: params.accessToken,
})
ãã¡ã¤ã«ï¼ ./store/auth.ts
import { Module, ActionTree, GetterTree, MutationTree } from 'vuex'
import { LoginRequest, AuthApi } from '@/types/typescript-axios'
import Cookies, { CookieSetOptions } from 'universal-cookie'
import { RootState } from '@/types/index'
interface AuthState {
}
interface LoginParams {
basePath?: string,
value: LoginRequest,
cookie: Cookies,
stage: string,
}
export const state = (): AuthState => ({
})
export const getters: GetterTree<AuthState, RootState> = {
}
export const mutations: MutationTree<AuthState> = {
}
export const actions: ActionTree<AuthState, RootState> = {
async login(_ctx, params: LoginParams) {
try {
const { data } = await(new AuthApi({ basePath: params.basePath }))
.postAuthLogin(params.value)
params.cookie.set(
'accessToken',
data.accessToken,
{
secure: params.stage !== 'local',
maxAge: data.expiresIn,
} as CookieSetOptions,
)
} catch (error) {
throw error.response
}
},
}
export const auth: Module<AuthState, RootState> = {
namespaced: true,
getters,
mutations,
actions,
}
3. APIã®å¤æ´ã«è¿½å¾ãããããåãããã幸ã
ä¸è¨ã®ããã«OpenAPIããåã®æ å ±ãçæããããã³ãã¨ã³ãã§å©ç¨ããæµããå®è£ ãã¦ã¿ã¾ããã
APIã®å¤æ´ãææ¡ã追å¾ããã®ã¯ãããã³ãã¨ã³ãã®çµã¿è¾¼ã¿ãããä¸ã§ãªããªã骨ã®æããé¨åããããã¾ããããGeneratorãå©ç¨ãããã¨ã§ãã«ãã¨ã©ã¼ãªã©ã§ä¿®æ£ãããã¤ã³ããææ¡ã§ããã®ã§äºæ ãã«ããç¶æ ãä½ãããã¨æãã¾ãã
ãã¨ã¯ãããã³ãã¨ã³ãã®ãã¹ãã«ãã¾ãçµã¿è¾¼ã¿ãããªã¨æã£ã¦ããã¨ããã§ããããããã¾ã åºæ¥ã¦ããªãã®ã§ãä»å¾ã®èª²é¡ã¨ããã¦ããã ãã¾ãã
åè
*1 https://openapi-generator.tech/
*2 OpenAPI generatorã試ãã¦ã¿ã
*3 https://github.com/OpenAPITools/openapi-generator