scaffdog で EntryPoints のテンプレート化
EntryPoints のテンプレート化
これが、今回の工数削減の肝になる。
毎度おなじみの scaffdog
にてテンプレート化する。
$ yarn add scaffdog --dev
それに際し、テンプレート化しやすいようにリファクタリングし、それをテンプレートにした: .scaffdog/template.md
リファクタリングの方針としては、API エンドポイントの実体である route.tsx
をいじらないように、それぞれ違う部分を設定ファイルに切り出したことだ。そうすることで、Review は設定だけ見ればよくなる。また、悩んだところではあるが、できるだけファイルが分散しないように設定ファイルをまとめた。まとめたが、セキュリティを考えると、まとめない方がより安全かも知れない。
実際のテンプレートは長いので、直接見ていただくとし、設定部分だけ。
---
name: 'API'
root: './'
output: '**/*'
ignore: []
questions:
module: 'Enter module name(singular and kebab like item-category)'
tag: 'Enter tag name such as user'
isIdNumber:
confirm: 'Is type of id number? (if cuid, then no)'
isAuthRequired:
confirm: 'Is auth required api?'
---
questions で、module 名、API 仕様書で分類される tag 名、slug パラメータの id が number 型かどうか、Auth が必要かどうかなどを聞いている。 scaffdog では、module 名などのようなパラメータを、複数形にしたり、大文字・小文字・Pascal, Camel などなどに変換できるので、単数形だけ聞いておけば良い。 詳細は、scaffdog のドキュメンテーション を参照。実に色んなことができる。
{
"scripts": {
"scaffold": "scaffdog generate"
},
...
}
yarn scaffold
で動く。
├── src
│ ├── app/api
│ │ └── Xxxx
│ │ ├── [id]
│ │ │ └── route.ts
│ │ └── route.ts
│ └── schemas/config
│ ├── models
│ │ └── XxxxSchema.ts
│ ├── ExtendedModels.ts
│ └── index.ts
└── tools/openapi
└── EntryPoints.ts
が更新される。
EntryPoint 新規作成の流れは、
prisma/schema.prisma
に model を書くnpx prisma migrate dev
して DB に反映する(と共に、諸々生成する)yarn scaffold
してファイルを生成/更新src/schemas/config/ExtendedModels.ts
で description, example を書くsrc/schemas/config/models/XxxxSchema.ts
で入出力を書くyarn openapi:generate
でpublic/openapi.json
を更新する
となる。
XxxxSchema.ts の中身
Prisma 部分
// selected columns. if select all, leave it as {}
export const XxxxPrismaSelect = {};
// included columns
export const XxxxPrismaInclude = {
posts: {
orderBy: [{ updatedAt: 'desc' }, { createdAt: 'desc' }],
select: {
id: true,
title: true,
createdAt: true,
},
},
bookmarks: {
select: {
postId: true,
post: {
select: {
title: true,
createdAt: true,
author: {
select: {
id: true,
userName: true,
imageUrl: true,
},
},
},
},
},
},
_count: {
select: {
posts: true,
bookmarks: true,
},
},
};
// connect etc. if no relational post/put query, just return params.
export function formatXxxxParams(params: Partial<RequestType>) {
const { postId, userId, ...rest } = params;
let formattedParams: any = { ...rest };
if (postId)
formattedParams = {
...formattedParams,
post: { connect: { id: +postId } },
};
if (userId)
formattedParams = { ...formattedParams, user: { connect: { id: userId } } };
return formattedParams;
}
ほぼほぼ、通常の Prisma の書き方で、select するもの、include するもの、connect 等するものなどを記述するようにした。
OpenAPI 部分
コードは省略するが、prisma クエリに合わせ、request, response のスキーマを記述すると共に、API ドキュメントで使う説明を追加する。また、各メソッドや slug パラメータなどの組み合わせによるパスの設定もしている。エンドポイントによっては不要なパスがあるが、その場合は不要なパスの設定を削除する。 設定が実際にはどう使われるのかは、src/schemas/BuildOpenApiSchema.ts を参照。
それでも…
というように、極力開発者によって工夫の余地がなくなるように設計してあるが、それでも route.tsx
をいじってくる開発者もいるので、route.tsx
を個別に持たせるのではなく、Dynamic Route 化してしまうのも良いかも知れない。今回それはやっていないが、工数面、メンテナンス性等を重視した設計である旨を伝え、P/R はリジェクトする。