📃

TypeSpecを使ってみる

2023/03/13に公開1

今回の内容はこちらにあります。
https://github.com/HidakaRintaro/typespec-practise

TypeSpec[1]とは

TypeSpec is a language for describing cloud service APIs and generating other API description languages, client and service code, documentation, and other assets. TypeSpec provides highly extensible core language primitives that can describe API shapes common among REST, OpenAPI, GraphQL, gRPC, and other protocols.

https://github.com/microsoft/typespec より

公式ドキュメント
playground

実際に使ってみる

今回は Swagger Petstoreを再現できるように記述してみます。
もし、すでに Swagger Editor を使ったことがあり内容が表示される場合はLocalStorageのswagger-editor-contentを削除するとデフォルトの表示になると思います。

インストール手順は公式を見ればわかりますが一応記述

インストール

ドキュメント
ただ、グローバルにインストールする嫌だったためその手順で書いてます。(tspコマンド前にnpxをつけるだけ)

# node.js 16 LTS

npm install @typespec/compiler

# VS Codeの拡張機能 (必要なければ不要)
npx tsp code install 

# 各質問に答える
npx tsp init

npx tsp install

ここまで行うと下記のファイルが生成されると思います。

  • main.tsp
  • node_modules/
  • package-lock.json
  • package.json
  • tspconfig.yaml

main.tspのコード
main.tsp
import "@typespec/rest";
import "@typespec/openapi3";

using TypeSpec.Http;

@service({
  title: "Swagger Petstore - OpenAPI 3.0",
  version: "1.0.11",
})
@doc("""
  This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
  Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
  You can now help us improve the API whether it's by making changes to the definition itself or to the code.
  That way, with time, we can improve the API in general, and expose some of the new features in OAS3.

  _If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_

  Some useful links:
  - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
  - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
""")
@server("https://petstore3.swagger.io/api/v3", "")
@useAuth(
  OAuth2Auth<[
    {
      type: OAuth2FlowType.implicit,
      authorizationUrl: "https://petstore3.swagger.io/oauth/authorize",
      // DOCS: https://github.com/microsoft/typespec/issues/1113
      // 説明文が追加できない問題
      scopes: ["write:pets", "read:pets"],
    }
  ]> | ApiKeyAuth<ApiKeyLocation.header, "api_key">
)
namespace TypeSpecSample;
namespace Auth {
  @tag("pet")
  @route("/pet")
  namespace PetAPI {
    interface Pets {
      @summary("Update an existing pet")
      @doc("Update an existing pet by Id")
      @put
      update(
        @header
        contentType: "application/json" | "application/xml" | "application/x-www-form-urlencoded",

        @doc("Update an existent pet in the store")
        @body
        pet: Pet
      ):
        | {
            @doc("Successful operation")
            @statusCode
            statusCode: 200;
            @header contentType: "application/json" | "application/xml";
            @body pet: Pet;
          }
        | {
            @doc("Invalid ID supplied")
            @statusCode
            statusCode: 400;
          }
        | {
            @doc("Pet not found")
            @statusCode
            statusCode: 404;
          }
        | {
            @doc("Validation exception")
            @statusCode
            statusCode: 405;
          };

      @summary("Add a new pet to the store")
      @doc("Add a new pet to the store")
      @post
      create(
        @header
        contentType: "application/json" | "application/xml" | "application/x-www-form-urlencoded",

        @doc("Create a new pet in the store")
        @body
        pet: Pet
      ): {
        @doc("Successful operation")
        @statusCode
        statusCode: 200;
        @header contentType: "application/json" | "application/xml";
        @body pet: Pet;
      } | {
        @doc("Invalid input")
        @statusCode
        statusCode: 405;
      };
    }

    @route("/findByStatus")
    interface FindByStatus {
      @summary("Finds Pets by status")
      @doc("Multiple status values can be provided with comma separated strings")
      @get
      list(
        @doc("Status values that need to be considered for filter")
        @query
        status?: "available" | "pending" | "sold"
      ): {
        @doc("successful operation")
        @statusCode
        statusCode: 200;
        @header contentType: "application/json" | "application/xml";
        @body pets: Pet[];
      } | {
        @doc("Invalid status value")
        @statusCode
        statusCode: 400;
      };
    }

    @route("/findByTags")
    interface FindByTags {
      @summary("Finds Pets by tags")
      @doc("Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.")
      @get
      list(
        @doc("Tags to filter by")
        @query
        tags?: string[]
      ): {
        @doc("successful operation")
        @statusCode
        statusCode: 200;
        @header contentType: "application/json" | "application/xml";
        @body pets: Pet[];
      } | {
        @doc("Invalid tag value")
        @statusCode
        statusCode: 400;
      };
    }

    @route("/{petId}")
    interface Details {
      @summary("Find pet by ID")
      @doc("Returns a single pet")
      @get
      read(
        @doc("ID of pet to return")
        @path
        petId: int64
      ): {
        @doc("successful operation")
        @statusCode
        statusCode: 200;
        @header contentType: "application/json" | "application/xml";
        @body pet: Pet;
      } | {
        @doc("Invalid ID supplied")
        @statusCode
        statusCode: 400;
      } | {
        @doc("Pet not found")
        @statusCode
        statusCode: 404;
      };

      @summary("Updates a pet in the store with form data")
      @post
      create(
        @doc("ID of pet that needs to be updated")
        @path
        petId: int64,

        @doc("Name of pet that needs to be updated")
        @query
        name?: string,

        @doc("Status of pet that needs to be updated")
        @query
        status?: string
      ): {
        @doc("Invalid input")
        @statusCode
        statusCode: 405;
      };

      @summary("Deletes a pet")
      @doc("delete a pet")
      @delete
      delete(
        @header api_key?: string,

        @doc("Pet id to delete")
        @path
        petId: int64
      ): {
        @doc("Invalid pet value")
        @statusCode
        statusCode: 400;
      };

      @summary("uploads an image")
      @route("/uploadImage")
      @post
      uploadImage(
        @doc("ID of pet to update")
        @path
        petId: int64,

        @doc("Additional Metadata")
        @query
        additionalMetadata?: string,
        @header contentType: "application/octet-stream",
        @body image: bytes
      ): {
        @doc("sucdcessful operation")
        @statusCode
        statusCode: 200;
        @header contentType: "application/json";
        @body apiResponse: ApiResponse;
      };
    }
  }

  @tag("store")
  @route("/store")
  namespace StoreAPI {
    interface Store {
      @summary("Returns pet inventories by status")
      @doc("Returns a map of status codes to quantities")
      @route("/inventory")
      @get
      read(): {
        @doc("successful operation")
        @statusCode
        statusCode: 200;
        @header contentType: "application/json";
        @body additionalProperties: Record<int32>;
      };
    }
  }
}

@tag("store")
@route("/store")
namespace StoreAPI {
  @route("/order")
  interface StoreOrder {
    @summary("Place an order for a pet")
    @doc("Place a new order in the store")
    @post
    create(
      @header
      contentType: "application/json" | "application/xml" | "application/x-www-form-urlencoded",
      @body order: Order
    ): {
      @doc("successful operation")
      @statusCode
      statusCode: 200;
      @header contentType: "application/json";
      @body order: Order;
    } | {
      @doc("Invalid input")
      @statusCode
      statusCode: 405;
    };
  }

  @route("/order/{orderId}")
  interface OrderDetails {
    @summary("Find purchase order by ID")
    @doc("For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.")
    @get
    read(
      @doc("IDof order that needs to be fetched")
      @path
      orderId: int64
    ): {
      @doc("successful operation")
      @statusCode
      statusCode: 200;
      @header contentType: "application/json" | "application/xml";
      @body order: Order;
    } | {
      @doc("Invalid ID supplied")
      @statusCode
      statusCode: 400;
    } | {
      @doc("Order not found")
      @statusCode
      statusCode: 404;
    };

    @summary("Delete purchase order by ID")
    @doc("For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors")
    @delete
    delete(
      @doc("ID of the order that needs to bedeleted")
      @path
      orderId: int64
    ): {
      @doc("Invalid IDsupplied")
      @statusCode
      statusCode: 400;
    } | {
      @doc("Order not found")
      @statusCode
      statusCode: 404;
    };
  }
}

@tag("user")
@route("/user")
namespace UserAPI {
  interface Users {
    @summary("Create user")
    @doc("This can only be done by the logged in user.")
    @post
    create(
      @header
      contentType: "application/json" | "application/xml" | "application/x-www-form-urlencoded",

      @doc("Created user object")
      @body
      user: User
    ): {
      @doc("successful operation")
      // NOTE: swaggerEditorではdefaultってなってるけど、defaultなんてコードねぇよ!
      @statusCode
      statusCode: 200;
      @header contentType: "application/json" | "application/xml";
      @body user: User;
    };

    @summary("Creates list of users with given input array")
    @doc("Creates list of users with given input array")
    @route("/createWithList")
    @post
    createWithList(
      @header contentType: "application/json",
      @body users: User[]
    ): {
      @doc("Successful operation")
      @statusCode
      statusCode: 200;
      @header contentType: "application/json" | "application/xml";
      @body user: User;
    };

    @summary("Logs user into the system")
    @route("/login")
    @get
    login(
      @doc("The user name for login")
      @query
      username?: string,

      @doc("The password for login in clear text")
      @query
      password?: string
    ): {
      @doc("successful operation")
      @statusCode
      statusCode: 200;
      // NOTE: 公式通りに指定するならこういう書き方じゃないの???
      // @header({
      //   contentType: "application/xml" | "application/json",

      //   @doc("calls per hour allowed by the user")
      //   `X-Rate-Limit`: int32,

      //   @doc("date in UTC when token expires")
      //   `X-Expires-After`: zonedDateTime,
      // })
      @header contentType: "application/xml" | "application/json";

      @body
      res: string;

      @doc("calls per hour allowed by the user")
      @header
      `X-Rate-Limit`: int32;

      @doc("date in UTC when token expires")
      @header
      `X-Expires-After`: zonedDateTime;
    } | {
      @doc("Invalid username/password supplied")
      @statusCode
      statusCode: 400;
    };

    @summary("Logs out current logged in user session")
    @route("/logout")
    @get
    logout(): {
      @doc("successful operation")
      // NOTE: swaggerEditorではdefaultってなってるけど、defaultなんてコードねぇよ!
      @statusCode
      statusCode: 200;
    };
  }

  @route("/{username}")
  interface FindByName {
    @summary("Get user by user name")
    @get
    read(
      @doc("The name that needs to be fetched. Use user1 for testing.")
      @path
      username: string
    ): {
      @doc("successful operation")
      @statusCode
      statusCode: 200;
      @header contentType: "application/json" | "application/xml";
      @body user: User;
    } | {
      @doc("Invalid username supplied")
      @statusCode
      statusCode: 400;
    } | {
      @doc("User not found")
      @statusCode
      statusCode: 404;
    };

    @summary("Update user")
    @doc("This can only be done by the logged in user.")
    @put
    update(
      @doc("name that need to be deleted")
      @path
      username: string,

      @header
      contentType: "application/json" | "application/xml" | "application/x-www-form-urlencoded",

      @doc("Update an existent user in the store")
      @body
      user: User
    ): {
      @doc("successful operation")
      // NOTE: swaggerEditorではdefaultってなってるけど、defaultなんてコードねぇよ!
      @statusCode
      statusCode: 200;
    };

    @summary("Delete user")
    @doc("This can only be done by the logged in user.")
    @delete
    delete(
      @doc("The name that needs to be deleted")
      @path
      username: string
    ): {
      @doc("Invalid username supplied")
      @statusCode
      statusCode: 400;
    } | {
      @doc("User not found")
      @statusCode
      statusCode: 404;
    };
  }
}

model Order {
  id?: int64;
  petId?: int64;
  quantity?: int32;
  shipDate?: zonedDateTime;

  @doc("Order Status")
  status?: "placed" | "approved" | "delivered";
  complete?: boolean;
}

model Customer {
  id?: int64;
  username: string;
  address?: Address[];
}

model Address {
  street?: string;
  city?: string;
  state?: string;
  zip?: string;
}

model Category {
  id?: int64;
  name?: string;
}

model User {
  id?: int64;
  username?: string;
  firstName?: string;
  lastName?: string;
  email?: string;
  password?: string;
  phone?: string;

  @doc("User Status")
  userStatus?: int32;
}

model Tag {
  id?: int64;
  name?: string;
}

model Pet {
  id?: int64;
  name: string;
  category?: Category;
  photoUrls: string[];
  tags?: Tag[];

  @doc("pet status in the store")
  status?: "available" | "pending" | "sold";
}

model ApiResponse {
  code?: int32;
  type?: string;
  message?: string;
}
openapi.yamlのコード
# yamlの生成方法
npx tsp compile .
tsp-output/@typespec/openapi3/openapi.yaml
openapi: 3.0.0
info:
  title: Swagger Petstore - OpenAPI 3.0
  version: 1.0.11
  description: |2-
      This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
      Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
      You can now help us improve the API whether it's by making changes to the definition itself or to the code.
      That way, with time, we can improve the API in general, and expose some of the new features in OAS3.

      _If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_

      Some useful links:
      - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
      - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
tags:
  - name: pet
  - name: store
  - name: user
paths:
  /pet:
    put:
      tags:
        - pet
      operationId: Pets_update
      summary: Update an existing pet
      description: Update an existing pet by Id
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
            application/xml:
              schema:
                $ref: '#/components/schemas/Pet'
        '400':
          description: The server could not understand the request due to invalid syntax.
        '404':
          description: The server cannot find the requested resource.
        '405':
          description: Client Error
      requestBody:
        description: Update an existent pet in the store
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Pet'
          application/xml:
            schema:
              $ref: '#/components/schemas/Pet'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Pet'
    post:
      tags:
        - pet
      operationId: Pets_create
      summary: Add a new pet to the store
      description: Add a new pet to the store
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
            application/xml:
              schema:
                $ref: '#/components/schemas/Pet'
        '405':
          description: Client Error
      requestBody:
        description: Create a new pet in the store
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Pet'
          application/xml:
            schema:
              $ref: '#/components/schemas/Pet'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Pet'
  /pet/findByStatus:
    get:
      tags:
        - pet
      operationId: FindByStatus_list
      summary: Finds Pets by status
      description: Multiple status values can be provided with comma separated strings
      parameters:
        - name: status
          in: query
          required: false
          description: Status values that need to be considered for filter
          schema:
            type: string
            enum:
              - available
              - pending
              - sold
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Pet'
                x-typespec-name: Pet[]
            application/xml:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Pet'
                x-typespec-name: Pet[]
        '400':
          description: The server could not understand the request due to invalid syntax.
  /pet/findByTags:
    get:
      tags:
        - pet
      operationId: FindByTags_list
      summary: Finds Pets by tags
      description: >-
        Multiple tags can be provided with comma separated strings. Use tag1,
        tag2, tag3 for testing.
      parameters:
        - name: tags
          in: query
          style: form
          explode: true
          required: false
          description: Tags to filter by
          schema:
            type: array
            items:
              type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Pet'
                x-typespec-name: Pet[]
            application/xml:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Pet'
                x-typespec-name: Pet[]
        '400':
          description: The server could not understand the request due to invalid syntax.
  /pet/{petId}:
    get:
      tags:
        - pet
      operationId: Details_read
      summary: Find pet by ID
      description: Returns a single pet
      parameters:
        - name: petId
          in: path
          required: true
          description: ID of pet to return
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
            application/xml:
              schema:
                $ref: '#/components/schemas/Pet'
        '400':
          description: The server could not understand the request due to invalid syntax.
        '404':
          description: The server cannot find the requested resource.
    post:
      tags:
        - pet
      operationId: Details_create
      summary: Updates a pet in the store with form data
      parameters:
        - name: petId
          in: path
          required: true
          description: ID of pet that needs to be updated
          schema:
            type: integer
            format: int64
        - name: name
          in: query
          required: false
          description: Name of pet that needs to be updated
          schema:
            type: string
        - name: status
          in: query
          required: false
          description: Status of pet that needs to be updated
          schema:
            type: string
      responses:
        '405':
          description: Client Error
    delete:
      tags:
        - pet
      operationId: Details_delete
      summary: Deletes a pet
      description: delete a pet
      parameters:
        - name: api_key
          in: header
          required: false
          schema:
            type: string
        - name: petId
          in: path
          required: true
          description: Pet id to delete
          schema:
            type: integer
            format: int64
      responses:
        '400':
          description: The server could not understand the request due to invalid syntax.
  /pet/{petId}/uploadImage:
    post:
      tags:
        - pet
      operationId: Details_uploadImage
      summary: uploads an image
      parameters:
        - name: petId
          in: path
          required: true
          description: ID of pet to update
          schema:
            type: integer
            format: int64
        - name: additionalMetadata
          in: query
          required: false
          description: Additional Metadata
          schema:
            type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
      requestBody:
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
  /store/inventory:
    get:
      tags:
        - store
      operationId: Store_read
      summary: Returns pet inventories by status
      description: Returns a map of status codes to quantities
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: integer
                  format: int32
                x-typespec-name: Record<int32>
  /store/order:
    post:
      tags:
        - store
      operationId: StoreOrder_create
      summary: Place an order for a pet
      description: Place a new order in the store
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '405':
          description: Client Error
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Order'
          application/xml:
            schema:
              $ref: '#/components/schemas/Order'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Order'
  /store/order/{orderId}:
    get:
      tags:
        - store
      operationId: OrderDetails_read
      summary: Find purchase order by ID
      description: >-
        For valid response try integer IDs with value <= 5 or > 10. Other values
        will generate exceptions.
      parameters:
        - name: orderId
          in: path
          required: true
          description: IDof order that needs to be fetched
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
            application/xml:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          description: The server could not understand the request due to invalid syntax.
        '404':
          description: The server cannot find the requested resource.
    delete:
      tags:
        - store
      operationId: OrderDetails_delete
      summary: Delete purchase order by ID
      description: >-
        For valid response try integer IDs with value < 1000. Anything above
        1000 or nonintegers will generate API errors
      parameters:
        - name: orderId
          in: path
          required: true
          description: ID of the order that needs to bedeleted
          schema:
            type: integer
            format: int64
      responses:
        '400':
          description: The server could not understand the request due to invalid syntax.
        '404':
          description: The server cannot find the requested resource.
  /user:
    post:
      tags:
        - user
      operationId: Users_create
      summary: Create user
      description: This can only be done by the logged in user.
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
            application/xml:
              schema:
                $ref: '#/components/schemas/User'
      requestBody:
        description: Created user object
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
          application/xml:
            schema:
              $ref: '#/components/schemas/User'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/User'
  /user/createWithList:
    post:
      tags:
        - user
      operationId: Users_createWithList
      summary: Creates list of users with given input array
      description: Creates list of users with given input array
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
            application/xml:
              schema:
                $ref: '#/components/schemas/User'
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/User'
              x-typespec-name: User[]
  /user/login:
    get:
      tags:
        - user
      operationId: Users_login
      summary: Logs user into the system
      parameters:
        - name: username
          in: query
          required: false
          description: The user name for login
          schema:
            type: string
        - name: password
          in: query
          required: false
          description: The password for login in clear text
          schema:
            type: string
      responses:
        '200':
          description: The request has succeeded.
          headers:
            x-rate-limit:
              required: true
              description: calls per hour allowed by the user
              schema:
                type: integer
                format: int32
            x-expires-after:
              required: true
              description: date in UTC when token expires
              schema:
                type: string
                format: date-time
          content:
            application/xml:
              schema:
                type: string
            application/json:
              schema:
                type: string
        '400':
          description: The server could not understand the request due to invalid syntax.
  /user/logout:
    get:
      tags:
        - user
      operationId: Users_logout
      summary: Logs out current logged in user session
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
  /user/{username}:
    get:
      tags:
        - user
      operationId: FindByName_read
      summary: Get user by user name
      parameters:
        - name: username
          in: path
          required: true
          description: The name that needs to be fetched. Use user1 for testing.
          schema:
            type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
            application/xml:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: The server could not understand the request due to invalid syntax.
        '404':
          description: The server cannot find the requested resource.
    put:
      tags:
        - user
      operationId: FindByName_update
      summary: Update user
      description: This can only be done by the logged in user.
      parameters:
        - name: username
          in: path
          required: true
          description: name that need to be deleted
          schema:
            type: string
      responses:
        '200':
          description: The request has succeeded.
      requestBody:
        description: Update an existent user in the store
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
          application/xml:
            schema:
              $ref: '#/components/schemas/User'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/User'
    delete:
      tags:
        - user
      operationId: FindByName_delete
      summary: Delete user
      description: This can only be done by the logged in user.
      parameters:
        - name: username
          in: path
          required: true
          description: The name that needs to be deleted
          schema:
            type: string
      responses:
        '400':
          description: The server could not understand the request due to invalid syntax.
        '404':
          description: The server cannot find the requested resource.
security:
  - OAuth2Auth:
      - write:pets
      - read:pets
  - ApiKeyAuth: []
components:
  schemas:
    Address:
      type: object
      properties:
        street:
          type: string
        city:
          type: string
        state:
          type: string
        zip:
          type: string
    ApiResponse:
      type: object
      properties:
        code:
          type: integer
          format: int32
        type:
          type: string
        message:
          type: string
    Category:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    Customer:
      type: object
      properties:
        id:
          type: integer
          format: int64
        username:
          type: string
        address:
          type: array
          items:
            $ref: '#/components/schemas/Address'
          x-typespec-name: Address[]
      required:
        - username
    Order:
      type: object
      properties:
        id:
          type: integer
          format: int64
        petId:
          type: integer
          format: int64
        quantity:
          type: integer
          format: int32
        shipDate:
          type: string
          format: date-time
        status:
          type: string
          enum:
            - placed
            - approved
            - delivered
          x-typespec-name: placed | approved | delivered
          description: Order Status
        complete:
          type: boolean
    Pet:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        category:
          $ref: '#/components/schemas/Category'
        photoUrls:
          type: array
          items:
            type: string
          x-typespec-name: string[]
        tags:
          type: array
          items:
            $ref: '#/components/schemas/Tag'
          x-typespec-name: Tag[]
        status:
          type: string
          enum:
            - available
            - pending
            - sold
          x-typespec-name: available | pending | sold
          description: pet status in the store
      required:
        - name
        - photoUrls
    Tag:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
        username:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        password:
          type: string
        phone:
          type: string
        userStatus:
          type: integer
          format: int32
          description: User Status
  securitySchemes:
    OAuth2Auth:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: https://petstore3.swagger.io/oauth/authorize
          scopes:
            write:pets: ''
            read:pets: ''
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api_key
servers:
  - url: https://petstore3.swagger.io/api/v3
    description: ''
    variables: {}

分からないorできなかったこと

こちらわかる方いらっしゃったらぜひコメントで教えてください🙇🏻‍♂️

  • modelのexample記述方法
  • Responseで各codeごとのdescriptionの記述方法
  • query parameterのenumでdefault値の記述方法
  • tagのdescription, external docsの記述方法
  • 認証(useAuth)の部分的反映方法(全体に対してしかでき無さそう?)
  • ライセンスの記述方法(おそらく未実装)

生成されたコードとの差分

現状上記の部分はできないことがわかっているのでそちら生成順序を調整したyamlとの差分をとってみます。
一応調整をしていない版の差分ものせておきます。

調整版
5,9c5,9
<   description: |2-
<       This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
<       Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
<       You can now help us improve the API whether it's by making changes to the definition itself or to the code.
<       That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
---
>   description: |-
>     This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
>     Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
>     You can now help us improve the API whether it's by making changes to the definition itself or to the code.
>     That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
98d105
<           required: false
99a107,108
>           required: false
>           explode: true
130,132c141
<       description: >-
<         Multiple tags can be provided with comma separated strings. Use tag1,
<         tag2, tag3 for testing.
---
>       description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
136,138d145
<           style: form
<           explode: true
<           required: false
139a147,148
>           required: false
>           explode: true
327,329c354
<       description: >-
<         For valid response try integer IDs with value <= 5 or > 10. Other values
<         will generate exceptions.
---
>       description: For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.
357,359c382
<       description: >-
<         For valid response try integer IDs with value < 1000. Anything above
<         1000 or nonintegers will generate API errors
---
>       description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
452,453c476
<             x-rate-limit:
<               required: true
---
>             X-Rate-Limit:
458,459c481
<             x-expires-after:
<               required: true
---
>             X-Expires-After:
702c759
<     ApiKeyAuth:
---
>     api_key:
708,709d764
<     description: ''
<     variables: {}
調整なし版
1c1
< openapi: 3.0.0
---
> openapi: 3.0.3
4,9c4,8
<   version: 1.0.11
<   description: |2-
<       This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
<       Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
<       You can now help us improve the API whether it's by making changes to the definition itself or to the code.
<       That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
---
>   description: |-
>     This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
>     Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
>     You can now help us improve the API whether it's by making changes to the definition itself or to the code.
>     That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
11c10
<       _If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_
---
>     _If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_
13,15c12,26
<       Some useful links:
<       - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
<       - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
---
>     Some useful links:
>     - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
>     - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
>   termsOfService: http://swagger.io/terms/
>   contact:
>     email: apiteam@swagger.io
>   license:
>     name: Apache 2.0
>     url: http://www.apache.org/licenses/LICENSE-2.0.html
>   version: 1.0.11
> externalDocs:
>   description: Find out more about Swagger
>   url: http://swagger.io
> servers:
>   - url: https://petstore3.swagger.io/api/v3
17a29,32
>     description: Everything about your Pets
>     externalDocs:
>       description: Find out more
>       url: http://swagger.io
18a34,37
>     description: Access to Petstore orders
>     externalDocs:
>       description: Find out more about our store
>       url: http://swagger.io
19a39
>     description: Operations about user
25d44
<       operationId: Pets_update
28,44c47
<       parameters: []
<       responses:
<         '200':
<           description: The request has succeeded.
<           content:
<             application/json:
<               schema:
<                 $ref: '#/components/schemas/Pet'
<             application/xml:
<               schema:
<                 $ref: '#/components/schemas/Pet'
<         '400':
<           description: The server could not understand the request due to invalid syntax.
<         '404':
<           description: The server cannot find the requested resource.
<         '405':
<           description: Client Error
---
>       operationId: updatePet
57,63c60
<     post:
<       tags:
<         - pet
<       operationId: Pets_create
<       summary: Add a new pet to the store
<       description: Add a new pet to the store
<       parameters: []
---
>         required: true
66c63
<           description: The request has succeeded.
---
>           description: Successful operation
73a71,74
>         '400':
>           description: Invalid ID supplied
>         '404':
>           description: Pet not found
75c76,86
<           description: Client Error
---
>           description: Validation exception
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
>     post:
>       tags:
>         - pet
>       summary: Add a new pet to the store
>       description: Add a new pet to the store
>       operationId: addPet
87a99,115
>         required: true
>       responses:
>         '200':
>           description: Successful operation
>           content:
>             application/json:
>               schema:
>                 $ref: '#/components/schemas/Pet'
>             application/xml:
>               schema:
>                 $ref: '#/components/schemas/Pet'
>         '405':
>           description: Invalid input
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
92d119
<       operationId: FindByStatus_list
94a122
>       operationId: findPetsByStatus
98d125
<           required: false
99a127,128
>           required: false
>           explode: true
101a131
>             default: available
108c138
<           description: The request has succeeded.
---
>           description: successful operation
115d144
<                 x-typespec-name: Pet[]
121d149
<                 x-typespec-name: Pet[]
123c151,155
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid status value
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
128d159
<       operationId: FindByTags_list
130,132c161,162
<       description: >-
<         Multiple tags can be provided with comma separated strings. Use tag1,
<         tag2, tag3 for testing.
---
>       description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
>       operationId: findPetsByTags
136,138d165
<           style: form
<           explode: true
<           required: false
139a167,168
>           required: false
>           explode: true
146c175
<           description: The request has succeeded.
---
>           description: successful operation
153d181
<                 x-typespec-name: Pet[]
159d186
<                 x-typespec-name: Pet[]
161c188,192
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid tag value
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
166d196
<       operationId: Details_read
168a199
>       operationId: getPetById
172d202
<           required: true
173a204
>           required: true
179c210
<           description: The request has succeeded.
---
>           description: successful operation
188c219
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid ID supplied
190c221,226
<           description: The server cannot find the requested resource.
---
>           description: Pet not found
>       security:
>         - api_key: []
>         - petstore_auth:
>             - write:pets
>             - read:pets
194d229
<       operationId: Details_create
195a231,232
>       description: ''
>       operationId: updatePetWithForm
199d235
<           required: true
200a237
>           required: true
206d242
<           required: false
212d247
<           required: false
218c253,257
<           description: Client Error
---
>           description: Invalid input
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
222d260
<       operationId: Details_delete
224a263
>       operationId: deletePet
227a267
>           description: ''
233d272
<           required: true
234a274
>           required: true
240c280,284
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid pet value
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
245d288
<       operationId: Details_uploadImage
246a290,291
>       description: ''
>       operationId: uploadFile
250d294
<           required: true
251a296
>           required: true
257d301
<           required: false
258a303
>           required: false
261,267d305
<       responses:
<         '200':
<           description: The request has succeeded.
<           content:
<             application/json:
<               schema:
<                 $ref: '#/components/schemas/ApiResponse'
273a312,322
>       responses:
>         '200':
>           description: successful operation
>           content:
>             application/json:
>               schema:
>                 $ref: '#/components/schemas/ApiResponse'
>       security:
>         - petstore_auth:
>             - write:pets
>             - read:pets
278d326
<       operationId: Store_read
281c329
<       parameters: []
---
>       operationId: getInventory
284c332
<           description: The request has succeeded.
---
>           description: successful operation
292c340,341
<                 x-typespec-name: Record<int32>
---
>       security:
>         - api_key: []
297d345
<       operationId: StoreOrder_create
300,309c348
<       parameters: []
<       responses:
<         '200':
<           description: The request has succeeded.
<           content:
<             application/json:
<               schema:
<                 $ref: '#/components/schemas/Order'
<         '405':
<           description: Client Error
---
>       operationId: placeOrder
320a360,368
>       responses:
>         '200':
>           description: successful operation
>           content:
>             application/json:
>               schema:
>                 $ref: '#/components/schemas/Order'
>         '405':
>           description: Invalid input
325d372
<       operationId: OrderDetails_read
327,329c374,375
<       description: >-
<         For valid response try integer IDs with value <= 5 or > 10. Other values
<         will generate exceptions.
---
>       description: For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.
>       operationId: getOrderById
332a379
>           description: ID of order that needs to be fetched
334d380
<           description: IDof order that needs to be fetched
340c386
<           description: The request has succeeded.
---
>           description: successful operation
349c395
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid ID supplied
351c397
<           description: The server cannot find the requested resource.
---
>           description: Order not found
355d400
<       operationId: OrderDetails_delete
357,359c402,403
<       description: >-
<         For valid response try integer IDs with value < 1000. Anything above
<         1000 or nonintegers will generate API errors
---
>       description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
>       operationId: deleteOrder
362a407
>           description: ID of the order that needs to be deleted
364d408
<           description: ID of the order that needs to bedeleted
370c414
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid ID supplied
372c416
<           description: The server cannot find the requested resource.
---
>           description: Order not found
377d420
<       operationId: Users_create
380,390c423
<       parameters: []
<       responses:
<         '200':
<           description: The request has succeeded.
<           content:
<             application/json:
<               schema:
<                 $ref: '#/components/schemas/User'
<             application/xml:
<               schema:
<                 $ref: '#/components/schemas/User'
---
>       operationId: createUser
403,410d435
<   /user/createWithList:
<     post:
<       tags:
<         - user
<       operationId: Users_createWithList
<       summary: Creates list of users with given input array
<       description: Creates list of users with given input array
<       parameters: []
412,413c437,438
<         '200':
<           description: The request has succeeded.
---
>         default:
>           description: successful operation
420a446,452
>   /user/createWithList:
>     post:
>       tags:
>         - user
>       summary: Creates list of users with given input array
>       description: Creates list of users with given input array
>       operationId: createUsersWithListInput
428c460,471
<               x-typespec-name: User[]
---
>       responses:
>         '200':
>           description: Successful operation
>           content:
>             application/json:
>               schema:
>                 $ref: '#/components/schemas/User'
>             application/xml:
>               schema:
>                 $ref: '#/components/schemas/User'
>         default:
>           description: successful operation
433d475
<       operationId: Users_login
434a477,478
>       description: ''
>       operationId: loginUser
438d481
<           required: false
439a483
>           required: false
444d487
<           required: false
445a489
>           required: false
450c494
<           description: The request has succeeded.
---
>           description: successful operation
452,453c496
<             x-rate-limit:
<               required: true
---
>             X-Rate-Limit:
458,459c501
<             x-expires-after:
<               required: true
---
>             X-Expires-After:
472c514
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid username/password supplied
477d518
<       operationId: Users_logout
478a520,521
>       description: ''
>       operationId: logoutUser
481,482c524,525
<         '200':
<           description: The request has succeeded.
---
>         default:
>           description: successful operation
487d529
<       operationId: FindByName_read
488a531,532
>       description: ''
>       operationId: getUserByName
491a536
>           description: 'The name that needs to be fetched. Use user1 for testing. '
493d537
<           description: The name that needs to be fetched. Use user1 for testing.
498c542
<           description: The request has succeeded.
---
>           description: successful operation
507c551
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid username supplied
509c553
<           description: The server cannot find the requested resource.
---
>           description: User not found
513d556
<       operationId: FindByName_update
515a559
>       operationId: updateUser
519d562
<           required: true
520a564
>           required: true
523,525d566
<       responses:
<         '200':
<           description: The request has succeeded.
537a579,581
>       responses:
>         default:
>           description: successful operation
541d584
<       operationId: FindByName_delete
543a587
>       operationId: deleteUser
547d590
<           required: true
548a592
>           required: true
553c597
<           description: The server could not understand the request due to invalid syntax.
---
>           description: Invalid username supplied
555,560c599
<           description: The server cannot find the requested resource.
< security:
<   - OAuth2Auth:
<       - write:pets
<       - read:pets
<   - ApiKeyAuth: []
---
>           description: User not found
562a602,650
>     Order:
>       type: object
>       properties:
>         id:
>           type: integer
>           format: int64
>           example: 10
>         petId:
>           type: integer
>           format: int64
>           example: 198772
>         quantity:
>           type: integer
>           format: int32
>           example: 7
>         shipDate:
>           type: string
>           format: date-time
>         status:
>           type: string
>           description: Order Status
>           example: approved
>           enum:
>             - placed
>             - approved
>             - delivered
>         complete:
>           type: boolean
>       xml:
>         name: order
>     Customer:
>       type: object
>       properties:
>         id:
>           type: integer
>           format: int64
>           example: 100000
>         username:
>           type: string
>           example: fehguy
>         address:
>           type: array
>           xml:
>             name: addresses
>             wrapped: true
>           items:
>             $ref: '#/components/schemas/Address'
>       xml:
>         name: customer
567a656
>           example: 437 Lytton
569a659
>           example: Palo Alto
571a662
>           example: CA
574,583c665,667
<     ApiResponse:
<       type: object
<       properties:
<         code:
<           type: integer
<           format: int32
<         type:
<           type: string
<         message:
<           type: string
---
>           example: '94301'
>       xml:
>         name: address
589a674
>           example: 1
592c677,680
<     Customer:
---
>           example: Dogs
>       xml:
>         name: category
>     User:
597a686
>           example: 10
600,607c689,712
<         address:
<           type: array
<           items:
<             $ref: '#/components/schemas/Address'
<           x-typespec-name: Address[]
<       required:
<         - username
<     Order:
---
>           example: theUser
>         firstName:
>           type: string
>           example: John
>         lastName:
>           type: string
>           example: James
>         email:
>           type: string
>           example: john@email.com
>         password:
>           type: string
>           example: '12345'
>         phone:
>           type: string
>           example: '12345'
>         userStatus:
>           type: integer
>           description: User Status
>           format: int32
>           example: 1
>       xml:
>         name: user
>     Tag:
613,619c718
<         petId:
<           type: integer
<           format: int64
<         quantity:
<           type: integer
<           format: int32
<         shipDate:
---
>         name:
621,631c720,721
<           format: date-time
<         status:
<           type: string
<           enum:
<             - placed
<             - approved
<             - delivered
<           x-typespec-name: placed | approved | delivered
<           description: Order Status
<         complete:
<           type: boolean
---
>       xml:
>         name: tag
632a723,725
>       required:
>         - name
>         - photoUrls
637a731
>           example: 10
639a734
>           example: doggie
643a739,740
>           xml:
>             wrapped: true
646c743,744
<           x-typespec-name: string[]
---
>             xml:
>               name: photoUrl
648a747,748
>           xml:
>             wrapped: true
651d750
<           x-typespec-name: Tag[]
653a753
>           description: pet status in the store
658,663c758,760
<           x-typespec-name: available | pending | sold
<           description: pet status in the store
<       required:
<         - name
<         - photoUrls
<     Tag:
---
>       xml:
>         name: pet
>     ApiResponse:
666c763
<         id:
---
>         code:
668,669c765,766
<           format: int64
<         name:
---
>           format: int32
>         type:
671,677c768
<     User:
<       type: object
<       properties:
<         id:
<           type: integer
<           format: int64
<         username:
---
>         message:
679,692c770,789
<         firstName:
<           type: string
<         lastName:
<           type: string
<         email:
<           type: string
<         password:
<           type: string
<         phone:
<           type: string
<         userStatus:
<           type: integer
<           format: int32
<           description: User Status
---
>       xml:
>         name: '##default'
>   requestBodies:
>     Pet:
>       description: Pet object that needs to be added to the store
>       content:
>         application/json:
>           schema:
>             $ref: '#/components/schemas/Pet'
>         application/xml:
>           schema:
>             $ref: '#/components/schemas/Pet'
>     UserArray:
>       description: List of user object
>       content:
>         application/json:
>           schema:
>             type: array
>             items:
>               $ref: '#/components/schemas/User'
694c791
<     OAuth2Auth:
---
>     petstore_auth:
700,702c797,799
<             write:pets: ''
<             read:pets: ''
<     ApiKeyAuth:
---
>             write:pets: modify pets in your account
>             read:pets: read your pets
>     api_key:
704d800
<       in: header
706,709c802
< servers:
<   - url: https://petstore3.swagger.io/api/v3
<     description: ''
<     variables: {}
---
>       in: header

最後に

あくまで僕の備忘録のようなものなので間違った記述とかがあるかもしれません。
個人的には書きやすかったので、個人開発などで使ってみようと思いました。
ただ、prettier(formatter)で?!?!?みたいな整形がされたりすることもあったのでその辺りはもう少し調べてみようと思います。

有識者の方がいらっしゃたっらぜひコメントで不備など指摘していただけると嬉しいです🙇🏻‍♂️

脚注
  1. 元々cadlというプロジェクト ↩︎

GitHubで編集を提案

Discussion