OpenAPI CLIの使用:カスタム前処理


の主な特徴openapi-cli は拡張性です.拡張する方法は三つあります.preprocessors, rules, and decorators . 比較すると、Spectral 唯一のカスタムルールをサポートします.
このチュートリアルでは、プリプロセッサから始めます.検証とリンギングの前にOpenAPI記述ドキュメントを変換するために使用されます.カスタム・プリプロセッサがエラーがちである傾向があるので、あなたに気をつけてください.

例:拡張可能な列挙体

In our Stargate Network API there is a Stargate.yaml schema 列挙体で定義された2つのプロパティを指定します.state and environment . 我々は、我々はすべての潜在的な値をキャプチャしたと思うかもしれませんが、我々は確信することはできません.
Zalando API guidelines and The Design of Web APIs by Arnaud Lauret 特に、出力でAPI互換性が発生する可能性があることを警告します.
シナリオを想像してください.我々は、APIの初期バージョンのSDKを生成し、ジェネレータは、選択したプログラミング言語の列挙を使用するのに十分スマートでした.いくつかの時間後に我々は新しいAPIバージョンをプッシュenvironment することもできますSTAR . SDKの最初のバージョンにまだある顧客は、この値を含んでいるAPI応答を処理することができません.おそらくほとんどのクライアントは何か何かを処理可能な実体例外でクラッシュするでしょう.
したがって、Zalandoと同様に、カスタムを使用しますvendor extension 可能な値を文書化する.私はそれを呼び出すx-aviskase-enum ちょうど他の拡張子との競合を導入しない場合.Commit fa78766 .

ドキュメンテーションにおける表面値

Oops, now there is no way to see known values in the generated reference docs. The manual fix is to add these values to the description . But this is too cumbersome, especially if you’ll ever want to change presentation format.

Preprocessor for the rescue! What we want it to do:

  1. Find all properties with x-aviskase-enum property.
  2. Grab the list of values, format them nicely, and add it to the description . Make sure not to overwrite existing description if it’s already present!

プリプロセッサの追加

Let’s create a preprocessor first ./plugins/preprocessors/add-enum-to-description.js :

//@ts-check
module.exports = AddEnumToDescription;

/** @type { import('@redocly/openapi-core/src/visitors').Oas3Preprocessor } */
function AddEnumToDescription(options) {
  const vendorExtension = options.vendorExtension || 'x-enum';
  return {
    Schema(schema) {
      if (schema[vendorExtension]) {
        schema.description = appendToDescription(schema[vendorExtension], schema.description);
      }
    },
  };
}

function appendToDescription(values, description) {
  let additionalDescription = `Possible values: ${values.map(v => `\`${v}\``).join(', ')}`;
  if (description) {
    return `${description}\n\n${additionalDescription}`;
  }
  return additionalDescription;
}

What’s happening here:

  • We export a preprocessor function AddEnumToDescription that accepts configuration options :
    • vendorExtension option is used to define extension name for extensible enumeration. If not provided, it equals to x-enum .
  • All openapi-cli preprocessors should return a visitor. In our case, we specifically indicate to take into account only schema nodes.
  • If a schema has defined extensible enumeration property, we update its description with formatted list of values.

Note: Per documentation, for type support you can use import('@redocly/openapi-cli').Oas3Preprocessor} . It never worked for me, so I use a “full path” import('@redocly/openapi-core/src/visitors').Oas3Preprocessor .


カスタムプラグインを使用してプリプロセッサを有効にする

Let’s keep our preprocessor (and the future ones) bundled inside one plugin via ./plugins/custom-preprocessors.js :

//@ts-check
const AddEnumToDescription = require('./preprocessors/add-enum-to-description');
const id = 'custom-preprocessors';

/** @type { import('@redocly/openapi-core/src/config/config').PreprocessorsConfig } */
const preprocessors = {
  oas3: {
    'add-x-enum-to-description': AddEnumToDescription,
  },
};

module.exports = {
  id,
  preprocessors,
};

Here we defined plugin’s id and a mapping between preprocessor’s name ( add-x-enum-to-description ) and its implementation.

Then we need to add this custom plugin to the .redocly.yaml and to enable the preprocessor:

...
lint:
  plugins:
    - './plugins/custom-preprocessors.js'
  preprocessors:
    custom-preprocessors/add-x-enum-to-description:
      vendorExtension: x-aviskase-enum
...
The final result is in commit 6654926 .

どのようにdocsに見えるか

Now, when we render a reference documentation, we can see all values with simple markdown formatting.


ところで、あなたが我々が正常に去ったかもしれない操作を見つけることができますかenum そしてなぜ?

なぜプリプロセッサを使うのですか?

As mentioned before, preprocessors might be brittle. We could have used decorator instead. I’ll show you the reason in the next article, but here is a sneak peek: we want to be able to lint modified descriptions !