ash-project / ash_json_api

The JSON:API extension for the Ash Framework
https://hexdocs.pm/ash_json_api
MIT License
62 stars 42 forks source link

Proof of concept openapi schema generation #63

Closed mbuhot closed 1 year ago

mbuhot commented 1 year ago

Relates to #62

TODO for an MVP implementation

Contributor checklist

mbuhot commented 1 year ago

Sample OpenAPI spec generated from the AshHQ guides resource.

You can paste it in to https://editor.swagger.io to validate it and see how it will look in SwaggerUI.

```yaml openapi: 3.0.3 info: description: description pending title: title pending version: api document version pending security: [] servers: [] tags: [] components: responses: errors: content: application/vnd.api+json: schema: $ref: '#/components/schemas/errors' description: General Error schemas: error: additionalProperties: false properties: code: description: An application-specific error code, expressed as a string value. type: string detail: description: A human-readable explanation specific to this occurrence of the problem. type: string id: description: A unique identifier for this particular occurrence of the problem. type: string links: $ref: '#/components/schemas/links' source: properties: parameter: description: A string indicating which query parameter caused the error. type: string pointer: description: A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute]. type: string type: object status: description: The HTTP status code applicable to this problem, expressed as a string value. type: string title: description: A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization. type: string type: object errors: items: $ref: '#/components/schemas/error' type: array uniqueItems: true guide: additionalProperties: false description: A "Resource object" representing a guide properties: attributes: additionalProperties: false description: An attributes object for a guide properties: category: type: string default: oneOf: - type: boolean - pattern: ^(true|false)$ type: string id: format: uuid type: string name: type: string order: oneOf: - type: integer - pattern: ^[1-9][0-9]*$ type: string route: type: string text: type: string text_html: type: string required: - id - order - name - text - category - route - default type: object id: type: string relationships: additionalProperties: false description: A relationships object for a guide properties: library_version: properties: data: description: An array of inputs for library_version items: description: Resource identifiers for library_version properties: id: type: string meta: additionalProperties: true type: object type: type: string required: - type - id type: object type: array uniqueItems: true type: object type: additionalProperties: false required: - type - id type: object link: description: 'A link **MUST** be represented as either: a string containing the link''s URL or a link object.' type: string links: additionalProperties: $ref: '#/components/schemas/link' type: object paths: /json_api/guides: get: parameters: - description: query param description pending in: query name: filter required: false schema: properties: category: type: string default: oneOf: - type: boolean - pattern: ^(true|false)$ type: string id: format: uuid type: string library_version: type: string name: type: string order: oneOf: - type: integer - pattern: ^[1-9][0-9]*$ type: string route: type: string text: type: string text_html: type: string type: object - description: query param description pending in: query name: include required: false schema: format: pending type: string - description: query param description pending in: query name: page required: false schema: properties: limit: pattern: ^[1-9][0-9]*$ type: string offset: pattern: ^[1-9][0-9]*$ type: string type: object - description: query param description pending in: query name: sort required: false schema: format: (id|-id|order|-order|name|-name|text|-text|text_html|-text_html|category|-category|route|-route|default|-default),* type: string responses: '200': content: application/vnd.api+json: schema: properties: data: description: An array of resource objects representing a guide items: $ref: '#/components/schemas/guide' type: array uniqueItems: true description: Success default: $ref: '#/components/responses/errors' post: parameters: - description: query param description pending in: query name: include required: false schema: format: pending type: string requestBody: content: application/vnd.api+json: schema: additionalProperties: false properties: data: additionalProperties: false properties: attributes: additionalProperties: false properties: category: type: string default: oneOf: - type: boolean - pattern: ^(true|false)$ type: string name: type: string order: oneOf: - type: integer - pattern: ^[1-9][0-9]*$ type: string route: type: string text: type: string required: - order - name - route - default type: object relationships: additionalProperties: false properties: {} type: object type: enum: - guide type: object required: - data type: object description: Body description pending required: true responses: '200': content: application/vnd.api+json: schema: properties: data: $ref: '#/components/schemas/guide' description: Success default: $ref: '#/components/responses/errors' /json_api/guides/{id}: get: parameters: - description: param description pending in: path name: id required: true schema: type: string - description: query param description pending in: query name: include required: false schema: format: pending type: string responses: '200': content: application/vnd.api+json: schema: properties: data: $ref: '#/components/schemas/guide' description: Success default: $ref: '#/components/responses/errors' patch: parameters: - description: param description pending in: path name: id required: true schema: type: string - description: query param description pending in: query name: include required: false schema: format: pending type: string requestBody: content: application/vnd.api+json: schema: additionalProperties: false properties: data: additionalProperties: false properties: attributes: additionalProperties: false properties: category: type: string default: oneOf: - type: boolean - pattern: ^(true|false)$ type: string name: type: string order: oneOf: - type: integer - pattern: ^[1-9][0-9]*$ type: string route: type: string text: type: string type: object id: format: uuid type: string relationships: additionalProperties: false properties: {} type: object type: enum: - guide type: object required: - data type: object description: Body description pending required: true responses: '200': content: application/vnd.api+json: schema: properties: data: $ref: '#/components/schemas/guide' description: Success default: $ref: '#/components/responses/errors' ```
zachdaniel commented 1 year ago

Looks awesome! We'll want to integrate the security section with the new ash_authentication so that it gets set automatically for you, I think. But for now giving them a way to edit it manually is perfectly fine :)

mbuhot commented 1 year ago

Closing this PR as I wasn't confident in making so many changes to the existing JsonSchema module to accomodate both OpenAPI 3.0 (extended subset of JsonSchema draft 04) and JsonSchema draft 06.