OpenAPI typescriptでファイルアップロード
openapi-typescriptでformat: binaryな型が単なるstringになってしまう
JSON形式のAPIを生成する場合は問題ないがfileuploadを扱う場合などにちょっと注意が必要そう。
"UploadImageRequest": {
"type": "object",
"required": [
"file"
],
"properties": {
"file": {
"type": "string",
"format": "binary",
"contentMediaType": "application/octet-stream"
}
}
},上記のようなJSONに対して、openapi typescriptは以下のようにformatを無視して単なるstring型として型を生成してしまう。
UploadImageRequest: {
/** Format: binary */
file: string;
};例えばclipboard dataをアップロードする場合は、Clipboard中のデータがBlobを継承する形で定義されている関係上Blobで扱うことができたほうが都合が良い場合がある。以下Clipboard中のFile定義の抜粋
/**
* The **`File`** interface provides information about files and allows JavaScript in a web page to access their content.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/File)
*/
interface File extends Blob {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */
readonly lastModified: number;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */
readonly name: string;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/webkitRelativePath) */
readonly webkitRelativePath: string;
}https://openapi-ts.dev/6.x/node#example-blob-types
openapi-typescriptにはこれに対応する方法としてpostTranfromという機能が用意されている。
https://github.com/openapi-ts/openapi-typescript/blob/main/docs/node.md#example-blob-types
ドキュメントは最新のコードベース事情を反映できていなかったので、githubのほうのdocsを参考にしたらうまくいった。
import openapiTS from "openapi-typescript";
import ts from "typescript";
const BLOB = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Blob")); // `Blob`
const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull()); // `null`
const ast = await openapiTS(mySchema, {
transform(schemaObject, metadata) {
if (schemaObject.format === "binary") {
return schemaObject.nullable
? ts.factory.createUnionTypeNode([BLOB, NULL])
: BLOB;
}
},
});openapi-fetchにおけるmultipart/formdataの扱い
https://openapi-ts.dev/openapi-fetch/api#bodyserializer
defaultではopenapi-fetchはrequest bodyをすべてJSON.stringifyしてしまうため、multipart/formdataなどでバイナリデータを扱いたい場合はbody-serializerを適用する必要がある。
ref. https://github.com/openapi-ts/openapi-typescript/issues/1214
ref. https://qiita.com/hagoromo2000/items/a862b3880654100d53fe