Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aliases should be kept as open api schemas #3445

Closed
3 tasks done
csaba-veezla opened this issue May 24, 2024 · 4 comments
Closed
3 tasks done

Aliases should be kept as open api schemas #3445

csaba-veezla opened this issue May 24, 2024 · 4 comments
Labels
bug Something isn't working needs-area

Comments

@csaba-veezla
Copy link

Clear and concise description of the problem

I feel like, this is almost a bug and not a feature request.

For a tsp declaration like this

import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";

using TypeSpec.Http;
using TypeSpec.Rest;

@doc("Example API")
@service({
  title: "Example",
})
namespace Example;

interface Examples{
  @get
  get(id: string): Elapsed;
}

model Elapsed {
  amount: integer;
  dateUnit: DateUnit;
}

alias DateUnit = "hours" | "days" | "weeks" | "months" | "years";

we get this open API spec

openapi: 3.0.0
info:
  title: Example
  description: Example API
tags: []
paths:
  /:
    get:
      operationId: Examples_get
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Elapsed'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
              required:
                - id
components:
  schemas:
    Elapsed:
      type: object
      required:
        - amount
        - dateUnit
      properties:
        amount:
          type: integer
        dateUnit:
          type: string
          enum:
            - hours
            - days
            - weeks
            - months
            - years

As you can see we lost a piece of information about the alias.
This could have easily resulted in the following:

openapi: 3.0.0
info:
  title: Example
  description: Example API
tags: []
paths:
  /:
    get:
      operationId: Examples_get
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Elapsed'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
              required:
                - id
components:
  schemas:
    Elapsed:
      type: object
      required:
        - amount
        - dateUnit
      properties:
        amount:
          type: integer
        dateUnit:
          type: string
          enum:
            - ref: '#/components/schemas/DateUnit'
    DateUnit:
      type: string
      enum:
        - hours
        - days
        - weeks
        - months
        - years

If the alias were to reference to models it could result into something like this:

    FilterValue:
      anyOf:
        - $ref: '#/components/schemas/MultiSelectFilterValue'
        - $ref: '#/components/schemas/DateFilterValue'

(If an alias is not pure models or scalars we can unpack them just like now.)

And with a result like this, a client generator can easily create a type for it or even a validator.

Or am I missing something in the docs and there is an option/flag for this?

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.
@timotheeguerin
Copy link
Member

Alias are by design in the TypeSpec type graph non existent so it is not possible to retrieve their name.

If you want to create a union declaration you can use the union keyword or an enum would work in your case too

union DateUnit {
  "hours",
  "days",
  "weeks",
  "months",
  "years",
}

enum DateUnitEnum {
  hours,
  days,
  weeks,
  months,
  years,
}

playground

@markcowl markcowl added the needs-info Mark an issue that needs reply from the author or it will be closed automatically label May 29, 2024
@csaba-veezla
Copy link
Author

csaba-veezla commented May 30, 2024

This was an issue on my part..
I'm fairly new to tsp and tried to use alias as it were union.. thanks for clearing it up.

Also, I saw that the results of circular dependencies do not play nice with the API spec emitter.

model MeuItem {
  label: string;
  // additional item props
}

model MenuGroup {
  label: string;
  // additional group props
  children: MenuItem | MenuGroup;
}

Is this a bug or is there another way to handle these cases?
In the API spec this will result in something like this:

 components:
  schemas:
    MenuGroup:
      type: object
      required:
        - label
        - children
      properties:
        label:
          type: string
        children:
          anyOf:
            - $ref: '#/components/schemas/MenuItem'
            - {}
    MenuItem:
      type: object
      required:
        - label
      properties:
        label:
          type: string

Edit: sorry for the late response.

@microsoft-github-policy-service microsoft-github-policy-service bot removed the needs-info Mark an issue that needs reply from the author or it will be closed automatically label May 30, 2024
@timotheeguerin timotheeguerin added the bug Something isn't working label Jul 10, 2024
@timotheeguerin
Copy link
Member

Created a new issue specially for that #3811

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs-area
Projects
None yet
Development

No branches or pull requests

3 participants