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

Generating OpenAPI enums from Model properties #2911

Closed
jasonvasquez opened this issue May 17, 2019 · 10 comments
Closed

Generating OpenAPI enums from Model properties #2911

jasonvasquez opened this issue May 17, 2019 · 10 comments
Labels

Comments

@jasonvasquez
Copy link

jasonvasquez commented May 17, 2019

Description

I have models in my application which have properties of various enum types, or arrays of enums. Is there a way in lb4 to generate OpenAPI enum types from those?

For instance:

enum Direction {
  North = "north",
  South = "south",
}

@model()
class Foo extends Model {
  ...
  @property.array(Direction, {required: true})
  directions: Direction[];
}

I would have hoped to be able to provide additional metadata to @property, along the lines of:

@property.array(Direction, {required: true, itemType: { enum: ["north", "south"]}})

For now, I've only had success describing them as numbers or strings. I've attempted to provide a Type<> object around these, but with no luck. If i'm understanding this comment correctly, it appears this may not be possible, but I would like to confirm: https://github.com/strongloop/loopback-next/blob/eeab36c352301d68a5f277907a072427d71a02b3/packages/repository-json-schema/src/build-schema.ts#L146-L147

If that's the case, are there plans to support types like this? In my specific case, I don't have need for any interpreted ORM behavior, as I'm not using the lb4 ORM in this scenario, simply describing API types for my application.

Current Behavior

Only primitives are generated for enums.

Expected Behavior

Enum types can be generated, given openapi metadata descriptions for possible values.

@raymondfeng
Copy link
Contributor

Please note TypeScript enum is only visible to the complier and we cannot reflect it at runtime. To mark it as an enum for openapi spec, you probably have to customize the itemType.

@dougal83
Copy link
Contributor

@raymondfeng Is this related to enum being a const? This twitter post makes a distinction but does that have no bearing on runtime in this context?

@raymondfeng
Copy link
Contributor

Not really. No matter how TypeScript transpiles the source code, there is no metadata visible at runtime. We wish tsc supports plugins to emit additional typings, such as string[].

@dougal83
Copy link
Contributor

Ah after further reading: Point 5, if only we had the appropriate design pattern to hand. 🔮 Sounds like a lot more code to me! :)

@bajtos
Copy link
Member

bajtos commented May 20, 2019

Recently, we landed #2685 which allows model properties to specify additional JSON Schema constraints. Would that work for you? I am thinking about something along the following lines (don't have to verify whether it works as intended):

@model()
class Foo extends Model {
  ...
  @property.array(Direction, {
    required: true,
    jsonSchema: {
      enum: ['north', 'south'],
    }
  })
  directions: Direction[];
}

@bajtos
Copy link
Member

bajtos commented May 20, 2019

For longer term, I think we should add first-class support for enum types, both at ORM and API layer.

See also the discussion in #1624

@jasonvasquez
Copy link
Author

@bajtos yes! That exactly what I was intuitively attempting at first hoping something like that could work. Agreed that #1624 heads in the right direction (for me at least), as specifying the shape of my data at the model level makes more sense than at the controller level. (I can always break out view models specifically for interaction with API clients if the structures need to be different than ORM-bound models)

@dhmlau
Copy link
Member

dhmlau commented May 31, 2019

@bajtos, do you think it's a duplicate of #1624 or should be labelled as feature?

@bajtos
Copy link
Member

bajtos commented Jun 3, 2019

In my experience, supporting ENUMS requires changes in several parts of the framework. We used to have an issue tracking this feature for LoopBack 3.x (see strongloop/loopback#1321), I created a new Epic issue specific to LB4: #3033

This particular GH issue seems to be centered around validation of ENUM model properties at OpenAPI level, which was already done for request bodies in #2685 and eventually will be done for other parameters in #1624

Let's close this issue as a duplicate.

@luncht1me
Copy link

I'm currently working on validating with enums, and can confirm the following behavior:

The @property decorator within the model doesn't validate enums. My enum AlertType here is just a basic string enum of arbitrary strings.

@property({
    type: 'string',
    required: true,
    jsonSchema: {
      enum: Object.values(AlertType),
    },
  })
type: AlertType

Using the @property decorator, Loopback does not validate that the data I pass for this property to create an instance of this model and I can send it any junk string and it accepts it.

BUT, if I move this out of the decorator, and into the actual openAPI Spec:

export const CreateSchema = {
    type: 'object',
    properties: {
      type: {
        type: 'string',
        enum: Object.values(AlertType), // <-- here
      },
[ ... ]

Loopback will now validate the property to only match the values I have within the enum AlertType.

Took me a little while to figure this out, perhaps my googlefu isn't as strong as I thought but, in case anyone searching for a similar use-case stumbles upon this, this is how I got custom types to validate via Loopback API.

Just for completion's sake, the CreateSchema above, is part of the @requestBody object:

export const CreateRequestBody = {
[ ... ]
content: {
      'application/json': {
        schema: CreateSchema,
      },
    },
[ ... ]
}

where:

@requestBody(CreateRequestBody)
data: [ ... ]

Maybe this will be useful to someone?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants