Slide 1

Slide 1 text

OpenAPI に静的解析と フォーマッターを導入する CTOA若手エンジニアコミュニティ勉強会 #5 うーたん

Slide 2

Slide 2 text

自己紹介 2

Slide 3

Slide 3 text

自己紹介 ● うーたん ○ X:@uutan1108 ● 株式会社ゆめみ ○ 新卒2年目 ○ サーバーサイドエンジニア ● 趣味 ○ アニメを観ること 3

Slide 4

Slide 4 text

先週に鹿児島で発表してきました

Slide 5

Slide 5 text

https://speakerdeck.com/ohmori_yusuke/hurokuraminku-and-shi-xing-tekiruweba huriwoshou-zuo-ri

Slide 6

Slide 6 text

見てください!

Slide 7

Slide 7 text

OpenAPI に静的解析とフォーマッターを導入する ~本題~ 7

Slide 8

Slide 8 text

OpenAPI とは

Slide 9

Slide 9 text

OpenAPI とは OpenAPI仕様(旧Swagger仕様) は、REST API用のAPI記述フォー マットです。 OpenAPI Specification (formerly Swagger Specification) is an API description format for REST APIs. An OpenAPI file allows you to describe your entire API, including https://ohmoriyusuke.github.io/openapi-sample/ What Is OpenAPI? https://swagger.io/docs/specification/about/

Slide 10

Slide 10 text

エンドポイント名 クエリパラメータ レスポンス https://ohmoriyusuke.github.io/openapi-sample/

Slide 11

Slide 11 text

OpenAPI は YAMLまたは JSON で記述できる

Slide 12

Slide 12 text

paths: /pets: get: summary: List all pets description: Retrieves a list of all pets, with pagination options. parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: "200": description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" https://github.com/OHMORIYUSUKE/openapi-sample/blob/main/openapi.yaml#L17-L51 openapi.yaml

Slide 13

Slide 13 text

paths: /pets: get: summary: List all pets description: Retrieves a list of all pets, with pagination options. parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: "200": description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" https://github.com/OHMORIYUSUKE/openapi-sample/blob/main/openapi.yaml#L17-L51 エンドポイント名 クエリパラメータ レスポンス

Slide 14

Slide 14 text

OpenAPI のYAMLから各言語のスキーマを 生成できる

Slide 15

Slide 15 text

{ "name": "open-api-sample", "version": "1.0.0", "description": "", "main": "index.js", "author": "", "license": "ISC", "scripts": { "lint": "spectral lint 'openapi.yaml'", "lint:ci": "spectral lint --format github-actions -F warn 'openapi.yaml'", "check": "prettier --check .", "fix": "prettier --write .", "build": "redocly build-docs -o ./dist/index.html ./openapi.yaml", "generate:typescript": "openapi-generator-cli generate -i openapi.yaml -g typescript-axios -o generated/ts" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.13.4", "@redocly/cli": "^1.13.0", "@stoplight/spectral-cli": "^6.11.1", "prettier": "^3.2.5" } } YAMLを指定して TypeScriptの スキーマを生成 package.json

Slide 16

Slide 16 text

/** * Retrieves a list of all pets, with pagination options. * @summary List all pets * @param {number} [limit] How many items to return at one time (max 100) * @param {*} [options] Override http request option. * @throws {RequiredError} */ listPets: async (limit?: number, options: RawAxiosRequestConfig = {}): Promise => { const localVarPath = `/pets`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; if (configuration) { baseOptions = configuration.baseOptions; } const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; if (limit !== undefined) { localVarQueryParameter['limit'] = limit; } 自動生成された コード generated/ts/api.ts

Slide 17

Slide 17 text

OpenAPI(YAML)から生成したコードを そのままアプリケーションに取り込める

Slide 18

Slide 18 text

YAMLもコードのように 静的解析とフォーマッターを入れて管理したい 生成 YAML → コード

Slide 19

Slide 19 text

OpenAPI(YAML)に 静的解析とフォーマッターを導入する

Slide 20

Slide 20 text

静的解析 @stoplight/spectral-cli

Slide 21

Slide 21 text

@stoplight/spectral-cli とは - カスタムルールセット: JSON または YAML オブジェクト を lint するためのカスタムルールを作成します。 - すぐに使えるルールセット: OpenAPI v2 & v3および AsyncAPIドキュメントの検証と lint Custom Rulesets: Create custom rules to lint JSON or YAML objects Ready-to-use Rulesets: Validate and lint OpenAPI v2 & v3 and AsyncAPI Documents @stoplight/spectral-cli https://www.npmjs.com/package/@stoplight/spectral-cli

Slide 22

Slide 22 text

使い方

Slide 23

Slide 23 text

npm install --save-dev @stoplight/spectral-cli @stoplight/spectral-cli をインストール

Slide 24

Slide 24 text

静的解析をする YAML

Slide 25

Slide 25 text

paths: /pets: get: summary: List all pets description: Retrieves a list of all pets, with pagination options. parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: "200": description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pats" openapi.yaml

Slide 26

Slide 26 text

静的解析を実行する

Slide 27

Slide 27 text

{ "name": "open-api-sample", "version": "1.0.0", "description": "", "main": "index.js", "author": "", "license": "ISC", "scripts": { "lint": "spectral lint 'openapi.yaml'", "lint:ci": "spectral lint --format github-actions -F warn 'openapi.yaml'", "check": "prettier --check .", "fix": "prettier --write .", "build": "redocly build-docs -o ./dist/index.html ./openapi.yaml", "generate:typescript": "openapi-generator-cli generate -i openapi.yaml -g typescript-axios -o generated/ts" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.13.4", "@redocly/cli": "^1.13.0", "@stoplight/spectral-cli": "^6.11.1", "prettier": "^3.2.5" } } spectral lint package.json

Slide 28

Slide 28 text

静的解析を実行 open-api-sample % npm run lint > [email protected] lint > spectral lint 'openapi.yaml' /project/open-api-sample/openapi.yaml 45:23 error invalid-ref '#/components/schemas/Pats' does not exist paths./pets.get.responses[200].content.application/json.schema.$ref 115:10 warning oas3-unused-component Potentially unused component has been detected. components.schemas.Pets ✖ 2 problems (1 error, 1 warning, 0 infos, 0 hints) 静的解析を実行

Slide 29

Slide 29 text

静的解析を実行後 open-api-sample % npm run lint > [email protected] lint > spectral lint 'openapi.yaml' /project/open-api-sample/openapi.yaml 45:23 error invalid-ref '#/components/schemas/Pats' does not exist paths./pets.get.responses[200].content.application/json.schema.$ref 115:10 warning oas3-unused-component Potentially unused component has been detected. components.schemas.Pets ✖ 2 problems (1 error, 1 warning, 0 infos, 0 hints) スペルミス(パスをミス) を指摘

Slide 30

Slide 30 text

paths: /pets: get: summary: List all pets description: Retrieves a list of all pets, with pagination options. parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: "200": description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pats" https://github.com/OHMORIYUSUKE/openapi-sample/blob/main/openapi.yaml#L17-L51 スペルミス openapi.yaml

Slide 31

Slide 31 text

フォーマッター prettier

Slide 32

Slide 32 text

prettier とは Prettierとは? 意見を取り入れたコード整形ツール 多くの言語をサポート ほとんどのエディタと統合できる オプションが少ない What is Prettier? An opinionated code formatter Supports many languages Integrates with most editors Has few options » YAML もサポート している Prettier stable https://prettier.io/

Slide 33

Slide 33 text

使い方

Slide 34

Slide 34 text

npm install --save-dev --save-exact prettier prettier をインストール

Slide 35

Slide 35 text

フォーマッターを実行する YAML

Slide 36

Slide 36 text

paths: /pets: get: summary: List all pets description: Retrieves a list of all pets, with pagination options. parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: "200": description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" openapi.yaml

Slide 37

Slide 37 text

フォーマッターを実行する

Slide 38

Slide 38 text

{ "name": "open-api-sample", "version": "1.0.0", "description": "", "main": "index.js", "author": "", "license": "ISC", "scripts": { "lint": "spectral lint 'openapi.yaml'", "lint:ci": "spectral lint --format github-actions -F warn 'openapi.yaml'", "check": "prettier --check .", "fix": "prettier --write .", "build": "redocly build-docs -o ./dist/index.html ./openapi.yaml", "generate:typescript": "openapi-generator-cli generate -i openapi.yaml -g typescript-axios -o generated/ts" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.13.4", "@redocly/cli": "^1.13.0", "@stoplight/spectral-cli": "^6.11.1", "prettier": "^3.2.5" } } prettier --check package.json

Slide 39

Slide 39 text

open-api-sample % npm run check > [email protected] check > prettier --check . Checking formatting... openapi.yaml [error] openapi.yaml: SyntaxError: Nested mappings are not allowed in compact mappings (20:16) [error] 18 | /pets: [error] 19 | get: [error] > 20 | summary: List all pets [error] | ^^^^^^^^^^^^^ [error] > 21 | description: Retrieves a list of all pets, with pagination options. [error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [error] > 22 | operationId: listPets [error] | ^ [error] 23 | tags: [error] 24 | - pets [error] 25 | parameters: All matched files use Prettier code style! フォーマッターを 実行

Slide 40

Slide 40 text

open-api-sample % npm run check > [email protected] check > prettier --check . Checking formatting... openapi.yaml [error] openapi.yaml: SyntaxError: Nested mappings are not allowed in compact mappings (20:16) [error] 18 | /pets: [error] 19 | get: [error] > 20 | summary: List all pets [error] | ^^^^^^^^^^^^^ [error] > 21 | description: Retrieves a list of all pets, with pagination options. [error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [error] > 22 | operationId: listPets [error] | ^ [error] 23 | tags: [error] 24 | - pets [error] 25 | parameters: All matched files use Prettier code style! descriptionのインデント がずれていることを指摘

Slide 41

Slide 41 text

paths: /pets: get: summary: List all pets description: Retrieves a list of all pets, with pagination options. parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer maximum: 100 format: int32 responses: "200": description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" https://github.com/OHMORIYUSUKE/openapi-sample/blob/main/openapi.yaml#L17-L51 インデントが ずれている openapi.yaml

Slide 42

Slide 42 text

YAML は見にくいので HTML で出力する

Slide 43

Slide 43 text

Redoc で YAML を見やすくする

Slide 44

Slide 44 text

ドキュメント生成 Redoc

Slide 45

Slide 45 text

Redoc とは Redoc は、OpenAPI (旧 Swagger) 定義からドキュメントを生成する オープン ソース ツールです。 Redoc is an open source tool for generating documentation from OpenAPI (formerly Swagger) definitions. https://ohmoriyusuke.github.io/openapi-sample/ Redocly / redoc https://github.com/Redocly/redoc

Slide 46

Slide 46 text

使い方

Slide 47

Slide 47 text

npm install --save-dev @redocly/cli Redoc をインストール

Slide 48

Slide 48 text

{ "name": "open-api-sample", "version": "1.0.0", "description": "", "main": "index.js", "author": "", "license": "ISC", "scripts": { "lint": "spectral lint 'openapi.yaml'", "lint:ci": "spectral lint --format github-actions -F warn 'openapi.yaml'", "check": "prettier --check .", "fix": "prettier --write .", "build": "redocly build-docs -o ./dist/index.html ./openapi.yaml", "generate:typescript": "openapi-generator-cli generate -i openapi.yaml -g typescript-axios -o generated/ts" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.13.4", "@redocly/cli": "^1.13.0", "@stoplight/spectral-cli": "^6.11.1", "prettier": "^3.2.5" } } redocly build-docs package.json

Slide 49

Slide 49 text

./dist/index.html にドキュメントが 生成される https://ohmoriyusuke.github.io/openapi-sample/

Slide 50

Slide 50 text

OpenAPI にも静的解析してフォーマッターを導 入して、綺麗なドキュメントも生成できた

Slide 51

Slide 51 text

GitHub : OHMORIYUSUKE/openapi-sample @stoplight/spectral-cli、prettier、Redoc を CIに 組み込んでいるので見てください!

Slide 52

Slide 52 text

宣伝 52

Slide 53

Slide 53 text

ゆめみ大技林 '24 技術書典で頒布している技術同人誌に 寄稿したので読んでください!ダウン ロードできます! 「読むとLTがしたくてたまらなくなる マニュアル」で書きました! 53

Slide 54

Slide 54 text

54

Slide 55

Slide 55 text

55

Slide 56

Slide 56 text

ご清聴ありがとうございました!