Skip to content

Add support for importing the pageSize decorator based on the relevant OpenAPI extension #9616

@baywet

Description

@baywet

Clear and concise description of the problem

Related https://github.com/microsoft/openai-openapi-pr/issues/568

Based on the following OpenAPI description, we should get the following TypeSpec definition imported

openapi: 3.0.0
info:
  title: Widget Service
  version: 0.0.0
tags:
  - name: Widgets
paths:
  /widgets:
    get:
      operationId: Widgets_list
      description: List widgets
      parameters:
        - name: page_size
          in: query
          required: true
          schema:
            type: integer
            format: int32
          #this is the extension that matters
          x-ms-list-page-size: true
          explode: false
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Widget'
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
        - Widgets
    post:
      operationId: Widgets_create
      description: Create a widget
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Widget'
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
        - Widgets
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Widget'
  /widgets/{id}:
    get:
      operationId: Widgets_read
      description: Read widgets
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            readOnly: true
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Widget'
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
        - Widgets
    patch:
      operationId: Widgets_update
      description: Update a widget
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            readOnly: true
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Widget'
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
        - Widgets
      requestBody:
        required: true
        content:
          application/merge-patch+json:
            schema:
              $ref: '#/components/schemas/WidgetMergePatchUpdate'
    delete:
      operationId: Widgets_delete
      description: Delete a widget
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            readOnly: true
      responses:
        '204':
          description: 'There is no content to send for this request, but the headers may be useful. '
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
        - Widgets
  /widgets/{id}/analyze:
    post:
      operationId: Widgets_analyze
      description: Analyze a widget
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            readOnly: true
      responses:
        '200':
          description: The request has succeeded.
          content:
            text/plain:
              schema:
                type: string
        default:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
        - Widgets
components:
  schemas:
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    Widget:
      type: object
      required:
        - id
        - weight
        - color
      properties:
        id:
          type: string
          readOnly: true
        weight:
          type: integer
          format: int32
        color:
          type: string
          enum:
            - red
            - blue
    WidgetMergePatchUpdate:
      type: object
      properties:
        weight:
          type: integer
          format: int32
        color:
          type: string
          enum:
            - red
            - blue
      description: ''
import "@typespec/http";
+ import "@typespec/openapi";

using Http;
+using OpenAPI;
@service(#{ title: "Widget Service" })
namespace DemoService;

model Widget {
  @visibility(Lifecycle.Read)
  id: string;

  weight: int32;
  color: "red" | "blue";
}

@error
model Error {
  code: int32;
  message: string;
}

@route("/widgets")
@tag("Widgets")
interface Widgets {
  /** List widgets */
-  @get list(@query page_size: int32): Widget[] | Error;
+ @get list(@query @extension("x-ms-list-page-size", true) @pageSize page_size: int32): Widget[] | Error;

  /** Read widgets */
  @get read(@path id: Widget.id): Widget | Error;

  /** Create a widget */
  @post create(@body widget: Widget): Widget | Error;

  /** Update a widget */
  @patch update(@path id: Widget.id, @body widget: MergePatchUpdate<Widget>): Widget | Error;

  /** Delete a widget */
  @delete delete(@path id: Widget.id): void | Error;
  /** Analyze a widget */
  @route("{id}/analyze") @post analyze(@path id: Widget.id): string | Error;
}

Here a couple of things are happening based on the presence of the extension:

  • the page_size decorator is added to the query parameter
  • the extension decorator is added to the query parameter
  • the import for openapi is added (if not already in scope)
  • the using for openapi is added (if not already in scope)

Checklist

  • Follow our Code of Conduct
  • Read the docs.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Metadata

Metadata

Assignees

Labels

openapi3:converterIssues for @typespec/openapi3 openapi to typespec converter

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions