OAS 3.1.0 の Schema Object をパースして TypeScript の型宣言を生成
JSON Schema に全乗っかりしたらしいので、既存のツールでパースした結果が、tsコード自動生成に使えるかどうか実験する
const fs = require("fs");
const path = require("path");
const jsYaml = require("js-yaml");
const jsonSchemaToTypeScript = require("json-schema-to-typescript");
const apiDocRaw = fs.readFileSync(path.resolve("assets/api.yaml")).toString()
const apiDoc = jsYaml.load(apiDocRaw);
const schemasEntries = Object.entries(apiDoc.components?.schemas ?? {})
const declPromises = schemasEntries.map(async ([name, schema]) => {
// stringify する JSON Schema 本体に、dereference 用の components プロパティをそのままくっつける
const parsable = { ...schema, components: apiDoc.components };
const schemaName = schema.title ?? name
return await jsonSchemaToTypeScript.compile(parsable, schemaName, {
bannerComment: "",
declareExternallyReferenced: false,
});
})
Promise.all(declPromises).then((decls) => {
const outDirPath = path.resolve("out")
fs.mkdirSync(outDirPath, { recursive: true })
const outPath = path.join(outDirPath, "models.ts");
fs.writeFileSync(outPath, decls.join("\n"));
})
↓ こういうのは出てくる。
readOnly
/writeOnly
のプロパティを捨てる機能はない(それはそう)。
$ref
した他のモデルの型名を(名前空間 prefix をつけるために)renameする機能はない(ほしい)。
export interface User {
id: number;
firstName: string;
lastName: string;
email: string;
dateOfBirth: string | null;
emailVerified: boolean;
createDate: string;
[k: string]: unknown;
}
export interface Article {
id: number;
author: User;
title: string;
body: string;
published: boolean;
publishedAt: string;
lastUpdatedAt: string;
[k: string]: unknown;
}
external schema ( $ref
してるスキーマ) の型名を変えられるようにしたい
import * as models from "./models.ts"
してるとき等
TSコード生成
Creating and Printing a TypeScript AST
jsonschemaの型付きでopenapidocをパース
writeOnly,readOnlyなど含んだ中間表現に一旦変形する←ここが独自実装になってしまうので避けたい
そこからオプションを受け取ってTSのAPIを使ってコード生成
writeOnly,readOnlyは、純粋なjsonschema to typescriptで考慮するものではないとは思うかも
オプションを拡張実装して
excludeWriteOnly → title: FooReadable
excludeReadOnly → title: FooWritable
で2回codegenする?
もちろんrecursiveで($ref先、properties, items の中も見る)
author:
$ref: '#/components/schemas/User'
readOnly: true
↑だとStoplightStudioで認識してくれなくて、GUIでいじると readOnly
が消えちゃう
↓だと author
が readOnly
なのは認識してくれて、GUIでいじっても消えない
author:
allOf:
- $ref: '#/components/schemas/User'
- readOnly: true
:thinking_face:
中間表現にパースした
各schemaのreadOnly/writeOnly版をrenderする ・・・ readOnly/writeOnlyプロパティを含むかどうか求める
circularなschemaも考慮してあげたい
ref | null どうする
CQRSを考えるとreadOnly/writeOnlyを使うのは良くないのでは。