Firestoreを使ってアプリとサーバを開発していて、
FlutterとCloud FunctionsやNitro Serverでモデルを共通化したいなと思い、
いろいろ調べてみたときの備忘録(*´ω`*)
TypeSpecでOpenAPIの定義を書いて、
それぞれの言語で生成するのがいいかもしれない。
まとめ
こんか感じだといいかも
- モデルの定義: TypeSpec
- TypeScriptっぽくOpenAPI定義が書けるので便利
- ts生成: openapi-typescript-codegen
- モデルごとに形を生成してくれるのがいい
- fetchを利用したAPI Clientも生成してくれる
- dart生成: openapi-generator(dart)
- doc生成: redoc/swagger-ui
- redocはきれいなのでAPIドキュメントとしていい
- ただ、try it outが使いたいのでswagger-uiも併用がよさそう
いろいろためしたときのリポジトリ
それぞれの簡単な使い方
ざっくりメモ
openapi.yamlの生成: TypeSpec
$ pnpm --package=@typespec/compiler dlx tsp init $ pnpm add -D @typespec/compiler $ pnpm install $ pnpm tsp compile # or $ pnpm tsp compile main.tsp $ ls tsp-output/@typespec/openapi3/openapi.yaml # オプションで出力先も変更できる $ pn tsp compile main.tsp \ --emit="@typespec/openapi3" \ --options='@typespec/openapi3.emitter-output-dir={project-root}/dist' $ ls dist/openapi.yaml
ts生成: openapi-typescript-codegen
$ pnpm dlx openapi-typescript-codegen --input ./dist/openapi.yaml --output ./dist/ts $ ls dist/ts core index.ts models services
models配下にcomponentsが生成され、
servicesにfetchを利用したAPI Clientが生成される。
enumはenumのまま出力されるが、unionにもできるらしい
ts生成: openapi-typescript
# インストール $ pnpm add -D openapi-typescript # スキーマの生成 $ pnpm openapi-typescript dist/openapi.yaml -o dist/schema.d.ts
openapi-fetchをつかって、
API Clientも生成できる。READMEのサンプルより。
import createClient from "openapi-fetch"; import type { paths } from "./dist/schema.d.ts"; // generated by openapi-typescript const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" }); const { data, // only present if 2XX response error, // only present if 4XX or 5XX response } = await client.GET("/blogposts/{post_id}", { params: { path: { post_id: "123" } }, }); await client.PUT("/blogposts", { body: { title: "My New Post" }, });
export interface components { schemas: { Pet: { id: number; name: string; none?: null; tag?: null | string | number; arr?: unknown[]; either?: string | null; }; }; responses: never; parameters: never; requestBodies: never; headers: never; pathItems: never; }
モデルごとにタイプができるわけではないので注意。
自前でtype aliasを書けばいいかも
dart生成: openapi-generator-cli(dart)
# インストール $ pnpm add -D @openapitools/openapi-generator-cli # スキーマ&Clinet生成 $ pnpm openapi-generator-cli generate -g dart -i dist/openapi.yaml -o dist/dart $ ls dist/dart README.md analysis_options.yaml doc git_push.sh lib pubspec.lock pubspec.yaml test
モデルとAPI Clientを含めて、dart packageを生成してくれる
enumはdartのenumでは生成してくれないっぽい
あとは、pubspec.yaml
でパス指定のdependenciesを追加すればOK
dependencies: myclient: path: ./dist/dart
doc生成: openapi-generator-cli
# インストール $ pnpm add -D @openapitools/openapi-generator-cli # htmlの生成 $ pnpm openapi-generator-cli generate -g html -i dist/openapi.yaml -o dist/doc-html $ ls dist/dart README.md analysis_options.yaml doc git_push.sh lib pubspec.lock pubspec.yaml test
doc生成: redoc
# インストール $ pnpm add -D redoc-cli # htmlの生成 $ pnpm redoc-cli build-docs openapi.yaml -o dist/doc-redoc/index.html $ ls dist/doc-redoc/index.html
doc生成: swagger-ui
htmlを生成してくれるCLIとかはないので、ちょっとめんどくさいい。。
- swagger-api/swagger-uiからzipをダウンロード
- zipを展開して、
dist
ディレクトリをコピー swagger-initializer.js
のurlを書き換えswagger-initializer.js
と同じ階層にopenapi.yaml
を配置
window.onload = function () { //<editor-fold desc="Changeable Configuration Block"> // the following lines will be replaced by docker/configurator, when it runs in a docker-container window.ui = SwaggerUIBundle({ - url: "https://petstore.swagger.io/v2/swagger.json", + url: "openapi.yaml", dom_id: '#swagger-ui', deepLinking: true, // 略... };
以上!! Firestoreを使ったりすると、モデル定義の共通化がめんどくさいので、だいぶ楽になるかも(*´ω`*)