Giter Site home page Giter Site logo

thim81 / openapi-format Goto Github PK

View Code? Open in Web Editor NEW
77.0 3.0 14.0 777 KB

Format an OpenAPI document by ordering, formatting and filtering fields.

License: MIT License

JavaScript 99.88% Dockerfile 0.12%
openapi-fields openapi cli filtering swagger oas openapi-tools openapi-tooling formatting sorting

openapi-format's Introduction

openapi-format icon

npm npm

openapi-format

Format an OpenAPI document by ordering, formatting and filtering fields.

The openapi-format CLI can load an OpenAPI file, sorts the OpenAPI fields by ordering them in a hierarchical order, format the casing of the fields and can output the file with clean indenting, to either JSON or YAML.

Next to the ordering & formatting, the CLI provides additional options to filter fields & parts of the OpenAPI document based on flags, tags, methods, operationID's and even unused components.

The openapi-format CLI has the option to convert an OpenAPI 3.0 document to an OpenAPI version 3.1.

Table of content

Use-cases

Public documentation: An OpenAPI document is a specification that evolves and changes. To facilitate working with the specification and publishing the document as public documentation, you want to deliver a clean and structured specification. OpenAPI-format helps you to organize the fields by sorting, formatting and filtering specific elements from the OpenAPI like internal endpoints, beta tags, ... and even unused schemas, examples, responses, ... with a clean and optimized OpenAPI document as a result.

Maintenance: When working on large OpenAPI documents or with multiple team members, the file can be become messy and difficult to compare changes. By sorting & formatting from time to time, the fields are all ordered in a structured manner & properly cased, which will help you to maintain the file with greater ease.

CI/CD pipelines: OpenAPI-format can be useful in CI/CD pipelines, where the OpenAPI is used as the source for other documents like Web documentation, Postman collections, test suites, ...

Features

  • Order OpenAPI fields in a default order
  • Order OpenAPI fields in a custom order
  • Order Components elements by alphabet
  • Format the casing (camelCase,PascalCase, ...) of component elements
  • Filter OpenAPI files based on methods
  • Filter OpenAPI files based on flags
  • Filter OpenAPI files based on flags values
  • Filter OpenAPI files based on tags
  • Filter OpenAPI files based on operationID's
  • Filter OpenAPI files based on operations definition
  • Filter OpenAPI files based on response content-types
  • Strip flags from OpenAPI files
  • Strip unused components from OpenAPI files
  • Convert OpenAPI 3.0 documents to OpenAPI 3.1
  • Rename the OpenAPI title
  • Support OpenAPI documents in JSON format
  • Support OpenAPI documents in YAML format
  • Format via CLI
  • Format via local or remote config files
  • Use as a Module
  • Aligned YAML parsing style with Stoplight Studio style
  • Support for OpenAPI 3.0
  • Support for OpenAPI 3.1 (beta)
  • Online playground (coming soon)

Installation

Local Installation (recommended)

While possible to install globally, we recommend that you add the openapi-format CLI to the node_modules by using:

$ npm install --save openapi-format

or using yarn...

$ yarn add openapi-format

Note that this will require you to run the openapi-format CLI with npx openapi-format your-openapi-file.yaml or, if you are using an older versions of npm, ./node_modules/.bin/openapi-format your-openapi-file.yaml.

Global Installation

$ npm install -g openapi-format

NPX usage

To execute the CLI without installing it via npm, use the npx method

$ npx openapi-format your-openapi-file.yaml

Command Line Interface

openapi-format.js <input-file> -o [output-file] [options]

Arguments:
  input-file   the OpenAPI document can be a local or remote file in JSON or YAML format
  output-file  the output file is optional and can be either a .json or .yaml file. 

Options:

  --output, -o          Save the formated OpenAPI file as JSON/YAML             [path]

  --sortFile            The file to specify custom OpenAPI fields ordering      [path]
  --casingFile          The file to specify casing rules                        [path]
  --filterFile          The file to specify filter rules                        [path]

  --no-sort             Don't sort the OpenAPI file                          [boolean]
  --sortComponentsFile  The file with components to sort alphabetically         [path]

  --rename              Rename the OpenAPI title                              [string]
  
  --convertTo           convert the OpenAPI document to OpenAPI version 3.1   [string]

  --configFile          The file with the OpenAPI-format CLI options            [path]

  --lineWidth           Max line width of YAML output                         [number]

  --json                Prints the file to stdout as JSON                    [boolean]
  --yaml                Prints the file to stdout as YAML                    [boolean]

  --help                Show help                                            [boolean]
  --version             Output the version number                            
  --verbose             Output more details of the filter process              [count]

OpenAPI format CLI options

Parameter Alias Description Input type Default Info
file the OpenAPI document can be a local or remote file in JSON or YAML format path to file required
--output -o save the formatted OpenAPI file as JSON/YAML path to file optional
--sortFile -s the file to specify custom OpenAPI fields ordering path to file defaultSort.json optional
--filterFile -f the file to specify filter setting path to file defaultFilter.json optional
--casingFile -c the file to specify casing setting path to file optional
--no-sort don't sort the OpenAPI file boolean FALSE optional
--sortComponentsFile sort the items of the components (schemas, parameters, ...) by alphabet path to file defaultSortComponents.json optional
--rename rename the OpenAPI title string optional
--convertTo convert the OpenAPI document to OpenAPI version 3.1 string optional
--configFile -c the file with all the format config options path to file optional
--lineWidth max line width of YAML output number -1 (Infinity) optional
--json prints the file to stdout as JSON FALSE optional
--yaml prints the file to stdout as YAML FALSE optional
--version output the version number optional
--verbose -v, -vv, -vvv verbosity that can be increased, which will show more output of the process optional
--help h display help for command optional

OpenAPI sort configuration options

The CLI will sort the OpenAPI document in the defined order liked defined per OpenAPI key/element. The fields that are not specified will keep their order like it is in the original OpenAPI document, so only defined fields will be re-ordered.

The default sorting based on the defined order (listed in the table below), which is stored in the defaultSort.json file.

You can easily modify this by specifying your own ordering per key, which can be passed on to the CLI (see below for an example on how to do this).

Key Ordered by OpenAPI reference
root - openapi
- info
- servers
- paths
- components
- tags
- x-tagGroups
- externalDocs
openapi-object
get - operationId
- summary
- description
- parameters
- requestBody
- responses
operationObject
post - operationId
- summary
- description
- parameters
- requestBody
- responses
operationObject
put - operationId
- summary
- description
- parameters
- requestBody
- responses
operationObject
patch - operationId
- summary
- description
- parameters
- requestBody
- responses
operationObject
delete - operationId
- summary
- description
- parameters
- requestBody
- responses
operationObject
parameters - name
- in
- description
- required
- schema
parameterObject
requestBody - description
- headers
- content
- links
request-body-object
responses - description
- headers
- content
- links
responses-object
content (By alphabet) responses-object
components - parameters
- schemas
components-object
schema - description
- type
- items
- properties
- format
- example
- default
schemaObject
schemas - description
- type
- items
- properties
- format
- example
- default
properties - description
- type
- items
- format
- example
- default
- enum

Have a look at the folder yaml-default and compare the "output.yaml" (sorted document) with the "input.yaml" (original document), to see how openapi-format have sorted the OpenAPI document.

OpenAPI filter options

By specifying the desired filter values for the available filter types, the openapi-format CLI will strip out any matching item from the OpenAPI document. You can combine multiple types to filter out a range of OpenAPI items.

For more complex use-cases, we can advise the excellent https://github.com/Mermade/openapi-filter package, which has extended options for filtering OpenAPI documents.

Type Description Type Examples
methods OpenAPI methods. array ['get','post','put']
inverseMethods OpenAPI methods that will be kept array ['get','post','put']
tags OpenAPI tags array ['pet','user']
inverseTags OpenAPI tags that will be kept array ['pet','user']
operationIds OpenAPI operation ID's array ['findPetsByStatus','updatePet']
inverseOperationIds OpenAPI operation ID's that will be kept array ['findPetsByStatus','updatePet']
operations OpenAPI operations array ['GET::/pets','PUT::/pets']
flags Custom flags array ['x-exclude','x-internal']
inverseFlags Custom flags that will kept array ['x-exclude','x-internal']
flagValues Custom flags with a specific value array ['x-version: 1.0','x-version: 3.0']
inverseFlagValues Custom flags with a value that will be kept array ['x-version: 1.0','x-version: 3.0']
responseContent Response Content types array ['application/json','application/html']
inverseResponseContent Response Content types that will kept array ['application/ld+json']
unusedComponents Unused components array ['examples','schemas']
stripFlags Custom flags that will be stripped array ['x-exclude','x-internal']
textReplace Search & replace values to replace array [{'searchFor':'Pet','replaceWith':'Dog'}]

Some more details on the available filter types:

Filter - methods/inverseMethods

=> methods: Refers to the Path Item Object

This will remove all fields and attached fields that match the verbs. In the example below, this would mean that all get, put, post items would be removed from the OpenAPI document.

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
            summary: Finds Pets by status
        put:
            summary: Update an existing pet

=> inverseMethods: This option does the inverse filtering, by keeping only the verbs defined and remove all other verbs.

Filter - tags

=> tags: Refers to the "tags" field from the "Operation Object" https://spec.openapis.org/oas/v3.0.3.html#operationObject

This will remove all fields and attached fields that match the tags. In the example below, this would mean that all items with the tags pet or user would be removed from the OpenAPI document.

For example:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        put:
            tags:
                - pet
            summary: Update an existing pet

=> inverseTags: This option does the inverse filtering, by keeping only the tags defined and remove all other tags, including the operations without a tags.

Filter - operationIds

=> operationIds: Refers to the "operationId" field from the Operation Object

This will remove specific fields and attached fields that match the operation ID's. In the example below, this would mean that the item with operationID findPetsByStatus would be removed from the OpenAPI document.

For example:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
            operationId: findPetsByStatus

=> inverseTags: This option does the inverse filtering, by keeping only the operationIds defined and remove all other operationIds, including the operations without an operationId.

Filter - operations

=> operations: Refers to a combination of a OpenAPI method & path from the Path Object & Path item

This will remove specific path items that match the operation definition PUT::/pets. In the example below, this would mean that the item with the path '/pets' and method 'PUT' would be removed from the OpenAPI document.

For example:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
            summary: Finds Pets by status
        put:
            summary: Update an existing pet

An operationId is an optional property. To offer support for OpenAPI documents that don't have operationIds, we have added the operation definition which is the unique combination of the OpenAPI method & path, with a :: separator symbol.

This will allow filtering for very specific OpenAPI items, without the need of adding operationIds to the OpenAPI document.

To facilitate managing the filtering, we have included wildcard options for the operations option, supporting the methods & path definitions.

REMARK: Be sure to put quotes around the target definition.

Strict matching example: "GET::/pets" This will target only the "GET" method and the specific path "/pets"

Method wildcard matching example: "*::/pets" This will target all methods ('get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace') and the specific path "/pets"

Path wildcard matching example: "GET::/pets/*" This will target only the "GET" method and any path matching any folder behind the "/pets", like "/pets/123" and "/pets/123/buy".

Method & Path wildcard matching example: "*::/pets/*" A combination of wildcards for the method and path parts is even possible.

Filter - flags/inverseFlags

=> flags: Refers to a custom property that can be set on any field in the OpenAPI document.

This will remove all fields and attached fields that match the flags. In the example below, this would mean that all items with the flag x-exclude would be removed from the OpenAPI document.

For example:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
            x-exclude: true

=> inverseFlags: This option does the inverse filtering, by keeping only the operations, components, tags, x-tagGroups that match the flag(s). This is a very aggressive option to keep only the items that are needed.

Filter - flagValues/inverseFlagValues

=> flagValues: Refers to a flag, custom property which can be set on any field in the OpenAPI document, and the combination with the value for that flag.

This will remove all fields and attached fields that match the flag with the specific value.

A flagValues example:

flagValues:
    - x-version: 1.0
    - x-version: 3.0

In the example below, this would mean that all items with the flag x-version that matches x-version: 1.0 OR x-version: 3.0 would be removed from the OpenAPI document.

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
            x-version: 1.0

The filter option flagValues also will remove flags that contain an array of values in the OpenAPI document.

A flagValues example:

flagValues:
    - x-versions: 1.0
    - x-versions: 2.0

In the example below, this would mean that all items with the flag x-versions, which is an array, that match x-version: 1.0 OR x-version: 3.0 would be removed from the OpenAPI document.

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
            x-versions:
                - 1.0
                - 3.0
                - 5.0

Have a look at flagValues and flagValues for array values for a practical example.

=> inverseFlagValues: This option does the inverse filtering, by keeping only the operations, components, tags, x-tagGroups that match the flag with the specific value. This is a very aggressive option to keep only the items that are needed.

Filter - responseContent/inverseResponseContent

=> ResponseContent: Refers to the Response Object's content

A content example:

content:
  - application/json

This will remove all the content that match the media types. In the example below, this would mean that all application/json content items would be removed from the OpenAPI document

Example before:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
  /pet:
    post:
      tags:
        - pet
      summary: Add a new pet to the store
      description: Add a new pet to the store
      operationId: addPet
      x-visibility: true
      responses:
        '200':
          description: Successful operation
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/Pet'
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
        '405':
          description: Invalid input

Example after:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
  /pet:
    post:
      tags:
        - pet
      summary: Add a new pet to the store
      description: Add a new pet to the store
      operationId: addPet
      x-visibility: true
      responses:
        '200':
          description: Successful operation
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/Pet'
        '405':
          description: Invalid input

=> inverseResponseContent: This option does the inverse filtering, by keeping only the content with media types defined and remove all other content.

Filter - unusedComponents

=> unusedComponents: Refers to a list of reusable component types, from which unused items will be removed.

This option allows you to strip the OpenAPI document from any unused items of the targeted components types. Any item in the list of OpenAPI components that is not referenced as $ref, will get marked and removed from the OpenAPI document.

REMARK: We will recursively strip all unused components, with a maximum depth of 10 times. This means that "nested" components, that become unused, will also get removed

Supported component types that can be marked as "unused":

  • schemas
  • parameters
  • examples
  • headers
  • requestBodies
  • responses

Filter - textReplace

=> textReplace: "search & replace" option to replace text in the OpenAPI specification

The textReplace provides a "search & replace" method, that will search for a text/word/characters in the OpenAPI description, summary, URL fields and replace it with another text/word/characters. This is very useful to replace data in the OpenAPI specification.

A textReplace example:

textReplace:
    - searchFor: 'Pets'
      replaceWith: 'Dogs'
    - searchFor: 'swagger.io'
      replaceWith: 'openapis.org'

This will replace all "Pets" with "Dogs" & "swagger.io" with "openapi.org" in the OpenAPI document.

Filter - stripFlags

=> stripFlags: Refers to a list of custom properties that can be set on any field in the OpenAPI document.

The stripFlags will remove only the flags, the linked parent and properties will remain. In the example below, this would mean that all flags x-exclude itself would be stripped from the OpenAPI document.

Example before:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
          x-exclude: true
          summary: Finds Pets by status

Example after:

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        get:
          summary: Finds Pets by status

Filter - preserveEmptyObjects

=> preserveEmptyObjects: Refers to any properties of your OpenAPI document, from which empty object values would be kept.

The preserveEmptyObjects will preserve all empty objects if set to true.

You can also pass a list of keys from which preserve empty objects. For instance a ['schema'] value would only prevent removal of empty objects having for key schema.

REMARK: Please note that openapi-format default behavior is to remove all empty objects from your document, except for examples.

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        post:
          requestBody:
            description: Create a new pet in the store
            required: true
            content:
              application/json:
                schema: {}

Example after (with preserveEmptyObjects: false):

openapi: 3.0.0
info:
    title: API
    version: 1.0.0
paths:
    /pets:
        post:
          requestBody:
            description: Create a new pet in the store
            required: true
            content:
              application/json: {}

OpenAPI formatting configuration options

Tools like spectral or speccy, or any of the linting tools, provide a manner to validate & lint OpenAPI specifications to be uniform. The linting tool informs about the incorrect usage of OpenAPI properties & inconsistent field names. This is very useful and helps to guard the quality of the OpenAPI specification. They inform which fields to correct so that the specification will comply with all the defined linting rules.

The openapi-format CLI formatting option can assist with keeping the field names consistent by automatically changing the casing of the properties/keys/names for the different elements in the OpenAPI document. The desired casing can be defined per OpenAPI key/element (see list below). The keys that are not specified will keep their casing like it is in the original OpenAPI document, so only for defined fields, the casing will be changed.

Key Description OpenAPI reference
operationId Changes operation ID's that are part of the Operations Object operation-object
properties Changes property keys of the schemas of the inline response/requestBody & components schemaObject
parametersCookie Changes the cookie name of the parameters inline & models in the components parameter-object
parametersPath Changes the path name of the parameters inline & models in the components parameter-object
parametersHeader Changes the header name of the parameters inline & models in the components parameter-object
parametersQuery Changes the query name of the parameters inline & models in the components parameter-object
componentsParametersCookie Changes the key of the cookie models in the components parameters sections & "$ref" links components-object
componentsParametersPath Changes the key of the path models in the components parameters sections & "$ref" links components-object
componentsParametersQuery Changes the key of the query models in the components parameters sections & "$ref" links components-object
componentsParametersHeader Changes the key of the header models in the components parameters sections & "$ref" links components-object
componentsSchemas Changes the key of the schema models in the components sections & "$ref" links components-object
componentsExamples Changes the key of the example models in the components sections & "$ref" links components-object
componentsHeaders Changes the key of the header models in the components sections & "$ref" links components-object
componentsResponses Changes the key of the response models in the components sections & "$ref" links components-object
componentsRequestBodies Changes the key of the request body models in the components sections & "$ref" links components-object
componentsSecuritySchemes Changes the key of the security schemes in the components sections & "$ref" links components-object

Casing options

Casing type Casing alias Description Example
๐Ÿช camelCase camelCase converts a strings to camelCase openapiFormat
๐Ÿ‘จโ€๐Ÿซ PascalCase PascalCase converts a strings to PascalCase OpenapiFormat
๐Ÿฅ™ kebab-case kebabCase converts a strings to kebab-case openapi-format
๐Ÿš‚ Train-Case TrainCase converts a strings to Train-Case Openapi-Format
๐Ÿ snake_case snakeCase converts a strings to snake_case openapi_format
๐Ÿ•Š Ada_Case AdaCase converts a strings to Ada_Case Openapi_Format
๐Ÿ“ฃ CONSTANT_CASE constantCase converts a strings to CONSTANT_CASE OPENAPI_FORMAT
๐Ÿ‘” COBOL-CASE cobolCase converts a strings to COBOL-CASE OPENAPI-FORMAT
๐Ÿ“ Dot.notation dotNotation converts a strings to Dot.notation openapi.format
๐Ÿ›ฐ Space case spaceCase converts a strings to Space case (with spaces) openapi format
๐Ÿ› Capital Case capitalCase converts a strings to Capital Case (with spaces) Openapi Format
๐Ÿ”ก lower case lowerCase converts a strings to lower case (with spaces) openapi format
๐Ÿ”  UPPER CASE upperCase converts a strings to UPPER CASE (with spaces) OPENAPI FORMAT

REMARK: All special characters are stripped during conversion, except for the @ and $, since they can be part of the query strings.

The casing options are provided by the nano NPM case-anything package.

Format casing - operationId

=> operationId: Refers to the operationId properties in the OpenAPI document.

Formatting casing example:

operationId: kebab-case

Example before:

openapi: 3.0.3
paths:
    /pets:
        get:
          operationId: getPets

openapi-format will format the "getPets" from the original camelcase to kebab-case.

Example after:

openapi: 3.0.3
paths:
    /pets:
        get:
          operationId: get-pets

Format casing - model & schema properties

=> properties: Refers to all the schema properties, that are defined inline in the paths request bodies & responses and the models in the components section of the OpenAPI document.

Formatting casing example:

properties: snake_case

Example before:

openapi: 3.0.3
components:
    schemas:
        UserModel:
            type: object
            properties:
                id:
                    type: integer
                    example: 10
                emailAddress:
                    type: string
                    example: [email protected]
                firstName:
                    type: string
                    example: John

The CLI will format all the properties like: "id", "username", "firstName" from the original camelcase to snake_case.

Example after:

openapi: 3.0.3
components:
    schemas:
        UserModel:
            type: object
            properties:
                id:
                    type: integer
                    example: 10
                email_address:
                    type: string
                    example: [email protected]
                first_name:
                    type: string
                    example: John

Format casing - component keys

=> componentsSchemas / componentsExamples / componentsParametersCookie / componentsParametersHeader / componentsParametersQuery / componentsParametersQuery / componentsParametersPath / componentsHeaders / componentsResponses / componentsRequestBodies / componentsSecuritySchemes: Refers to all the model objects that are defined in the components section of the OpenAPI document.

Formatting casing example:

componentsSchemas: PascalCase

Example before:

openapi: 3.0.3
paths:
    /orders:
        get:
            responses:
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/order-model'
components:
    schemas:
        userModel:
            type: object
        order-model:
            type: object
        pet_model:
            type: object

openapi-format will format all the component keys like: "userModel", "order-model", "pet_model" to PascalCase, including formatting all the "$ref" used in the OpenAPI document.

Example after:

openapi: 3.0.3
paths:
    /orders:
        get:
            responses:
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/OrderModel'
components:
    schemas:
        UserModel:
            type: object
        OrderModel:
            type: object
        PetModel:
            type: object

Format casing - parameter names

=> componentsParametersCookie / componentsParametersPath / componentsParametersQuery / componentsParametersHeader: Refers to "name" in the Parameters types: Path, Query or Header, which can be defined inline in the Path or as a reference in the components of the OpenAPI document.

Formatting casing example:

componentsParametersPath: kebab-case

Example before:

openapi: 3.0.3
paths:
    '/pet/{petId}':
        get:
            parameters:
                - name: petId
                  in: path
                  description: ID of pet to return
                - $ref: '#/components/parameters/LimitParam'
components:
    parameters:
        LimitParam:
            name: limitParam
            in: query
            description: max records to return

The CLI will format the "name" of the parameters: Path, Query or Header like: "petId", "limitParam" to kebab-case in the OpenAPI document.

Example after:

openapi: 3.0.3
paths:
    '/pet/{petId}':
        get:
            parameters:
                - name: pet-id
                  in: path
                  description: ID of pet to return
               - $ref: '#/components/parameters/LimitParam'
components:
    parameters:
        LimitParam:
            name: limit-param
            in: query
            description: max records to return

CLI sort usage

  • Format a spec with the default sorting and saves it as a new JSON file
$ openapi-format openapi.json -o openapi-formatted.json
  • Format a remote spec with the default sorting and saves it as a new JSON file
$ openapi-format https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/api-with-examples.json -o openapi-formatted.json
  • Format an OpenAPI JSON document with the default sorting and saves it as a new YAML file
$ openapi-format openapi.json -o openapi.yaml
  • Format an OpenAPI document with the default sorting and output it as JSON to STDOUT
$ openapi-format openapi.json --json
  • Format an OpenAPI document with the default sorting and output it as YAML to STDOUT
$ openapi-format openapi.json --yaml
  • Format an OpenAPI JSON document with the default sorting and save it as YAML
$ openapi-format openapi.json -o openapi.yaml
  • Format an OpenAPI document but skip the sorting and save it as a new JSON file
$ openapi-format openapi.json -o openapi-formatted.json --no-sort

This should keep the OpenAPI fields in the same order. This can be needed, when you only want to do a filtering or rename action.

  • Convert the OpenAPI 3.0 document to OpenAPI 3.1 but skip the sorting and save it as a new YAML file
$ openapi-format openapi.yaml -o openapi-3.1.yaml --no-sort --convertTo "3.1"

This will convert the OpenAPI 3.0 document into version 3.1 of OpenAPI, without any ordering or filtering. During the conversion, openapi-format will transform all OpenAPI 3.0 properties into the OpenAPI 3.1 properties, as described in the migration guide from Phil Sturgeon.

  • Format an OpenAPI document, including sorting all elements in the components section
$ openapi-format openapi.json -o openapi-formatted.json --sortComponentsFile ./test/json-sort-components/customSortComponents.json

This will sort all elements in the components ( components/schemas, components/parameters, components/headers, components/requestBodies, components/responses, ...) section by alphabet.

CLI filter usage

  • Format an OpenAPI document by filtering fields, default sorting and saves it as a new file

When you want to strip certain methods ,tags, operationIds, operations, flags you can pass a filterFile which contains the specific values for the methods ,tags, operationIds, operations, flags.

This can be useful to combine with the sorting, to end up with an order and filtered OpenAPI document.

example:

$ openapi-format openapi.json -o openapi-formatted.json --filterFile customFilter.yaml

where the customFilter.yaml would contain a combination of all the elements you want to filter out.

flags:
    - x-visibility
flagValues: [ ]
tags: [ ]
operationIds:
    - addPet
    - findPetsByStatus

CLI rename usage

  • Format an OpenAPI document by changing the title and saves it as a new JSON file

During CI/CD pipelines, you might want to create different results of the OpenAPI document. Having the option to rename them might make it easier to work with the results, so that is why we provide this command option.

$ openapi-format openapi.json -o openapi.json --rename "OpenAPI Petstore - OpenAPI 3.0"

which results in

before

{
    "openapi": "3.0.2",
    "info": {
        "title": "Petstore - OpenAPI 3.0",

after

{
    "openapi": "3.0.2",
    "info": {
        "title": "OpenAPI Petstore - OpenAPI 3.0",

CLI convertTo usage

๐Ÿ— BETA NOTICE: This feature is considered BETA since we are investigating the configuration syntax and extra formatting/casing capabilities.

  • Format & convert the OpenAPI document to OpenAPI version 3.1

openapi-format can help you to upgrade your current OpenAPI 3.0.x document to the latest version OpenAPI 3.1.

$ openapi-format openapi.json -o openapi-3.1.json --convertTo "3.1"

which results in all the changes described in the migration guide from Phil Sturgeon

before

{
    "openapi": "3.0.2",
    "info": {
        "title": "Petstore - OpenAPI",

after

{
    "openapi": "3.1.0",
    "info": {
        "title": "OpenAPI Petstore - OpenAPI",

CLI configuration usage

All the CLI options can be managed in a separate configuration file and passed along the openapi-format command. This will make configuration easier, especially in CI/CD implementations where the configuration can be stored in version control systems.

example:

$ openapi-format openapi.json --configFile openapi-format-options.json

The formatting will happen based on all the options set in the openapi-format-options.json file. All the available OpenAPI format options can be used in the config file.

AsyncAPI documents

For handling AsyncAPI documents, we have created a separate package asyncapi-format to allow customisation specific for AsyncAPI use-cases.

Stoplight Studio

We have adopted the YAML parsing style from Stoplight Studio, by leveraging the @stoplight/yaml package for handling the parsing of OpenAPI YAML files.

By using the Stoplight YAML parsing, the results will be slightly different from when using a normal YAML parsing library, like js-to-yaml. We appreciate the Stoplight Studio tool, since it is an excellent GUI for working with OpenAPI documents for non-OpenAPI experts who will be contributing changes. By adopting the Stoplight Studio YAML parsing, the potential risk of merge conflicts will be lowered, which is the main reason why we opted for using the @stoplight/yaml package.

Credits

This package is inspired by the @microsoft.azure/format-spec from @fearthecowboy. The original code was not available on GitHub, with the last update being 3 years ago, so to improve support and extend it we tried to reproduce the original functionality.

The filter capabilities from openapi-format are a light version grounded by the work from @MikeRalphson on the openapi-filter package.

The casing options available in openapi-format are powered by the excellent case-anything nano package from Luca Ban (@mesqueeb).

openapi-format's People

Contributors

bradworsfold-wd avatar coffelius avatar danielcontrerasaladro avatar dependabot[bot] avatar mamatsunami avatar rngtng avatar sferadev avatar shpoont avatar thim81 avatar vpzomtrrfrt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

openapi-format's Issues

Quotes around references to other files are incorrectly handled

Hi,

When formatting this file, that has references to schemas defined in other files:

openapi: 3.1.0
info:
  title: Example
  version: 1.0.0
paths:
  /v1/examples:
    get:
      summary: Get
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Example'
components:
  schemas:
    Example:
      type: object
      properties:
        id:
          $ref: './otherfile.yaml#/components/schemas/Id'

The following command npx openapi-format ./public/docs/example.yaml -o ./public/docs/example.yaml

Returns the following file:

openapi: 3.1.0
info:
  title: Example
  version: 1.0.0
paths:
  /v1/examples:
    get:
      summary: Get
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Example'
components:
  schemas:
    Example:
      type: object
      properties:
        id:
          $ref: ./otherfile.yaml#/components/schemas/Id

As you can see, quotes around $ref: './otherfile.yaml#/components/schemas/Id' get removed.
Can I fix this by modifying my file?

Empty security requirement ({}) is NOT supported.

When an empty security requirement is used in an OpenAPI descriptor, the security option in a filtered descriptor is populated with incorrect value: null.

Example:

  • "openapi-format": "^1.6.4"

  • A security definition in example.yaml:

    security:
        - BasicAuth: []
        - {}
    
  • Formatting command:

    npx openapi-format example.yaml -o example.openapi-format.yaml --filterFile filter.json
    
  • Content of filter.json:

    {
        "methods": [],
        "tags": [],
        "operationIds": [],
        "operations": [],
        "flags": [],
        "flagValues": [],
        "unusedComponents": [],
        "stripFlags": []
    }
    
  • The security definition in example.openapi-format.yaml:

    security:
        - BasicAuth: []
        - null
    

References:


In addition, filtering with the --no-sort option results in an error:

node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "[object Object]".] {
  code: 'ERR_UNHANDLED_REJECTION'
}

Node.js v17.0.1

"properties" casing changes not reflect in the "required" fields

In below example, properties of schemas are updated to snake_case as expected. But corresponding "required" fields left with older state (ex. "emailAddress" left as is after casing updates).

Formatting casing example:

properties: snake_case

Example before:

openapi: 3.0.3
components:
    schemas:
        UserModel:
            type: object
            properties:
                id:
                    type: integer
                    example: 10
                emailAddress:
                    type: string
                    example: [email protected]
                firstName:
                    type: string
                    example: John
            required:
                - id
                - emailAddress

Example after:

openapi: 3.0.3
components:
    schemas:
        UserModel:
            type: object
            properties:
                id:
                    type: integer
                    example: 10
                email_address:
                    type: string
                    example: [email protected]
                first_name:
                    type: string
                    example: John
            required:
                - id
                - emailAddress

Suggestion: Prettier like parameters to allow for easy script usage

Hi,
first of all, thanks for your tool that helps keeping API definitions and commits clean. โค๏ธ

prettier has a CLI that makes it really easy to use it in scripts, e.g. in CI:

  • --write replaces the input files
  • it accepts (multiple) paths/glob patterns
  • --check makes it fail if something changed

That might be a nice addition to openapi-format, too, although you can work arround the first two with find . -name '*.yaml' -exec yarn run openapi-format {} -o {} \;.

YAML comments are stripped

I have no idea if this is intentional, or just a difficult problem to solve, but comments are stripped from YAML OpenAPI specs.
This becomes a little bit problematic when the comments are meaningful to the openapi writer and help maintainability.

E.g:

# asdf
info:
  title: title
  description: description
  version: "3.1.0" # comment

Becomes

info:
  title: title
  description: description
  version: 3.1.0

Sort file error - no such file or directory "defaultSort.json"

I'm receiving this error whenever I run your tool.

Sort file error - no such file or directory "defaultSort.json"

It doesn't seem to be affecting anything as it completes and sorts my spec.
I've worked around by specifying --sortFile ""


Sorry, I don't have time to make a contribution here today -- But I wanted to let you know that I really appreciate you building this tool. It's solving a real pain point for us in our large spec file and I'm amazed you're the first one to build/share something like this. Thanks!

"properties" in the examples section gets incorrectly handled

If you have property named "properties" in the examples , it converts the object.

OpenAPI

  examples:
    sample-example:
      value:
           properties:
                  reportLocation: https://customername.example/1234567890/reports/ABC-123-DEF-456

results in

  examples:
    sample-example:
      value:
           properties:
                reportLocation:
                     '0': h
                     '1': t
                     '2': t
                    '3': p

Remove empty paths filter throws null error

Hi! I tried to use the package to filter my openapi schema but I'm getting TypeError: Cannot read properties of null (reading 'includes') from this line in openapi-format.js.

if (this.parent && this.parent.key === 'paths' && !httpVerbs.some(i => this.keys.includes(i))) {

In my api specification I have a request body schema that has paths among its properties so when this line of code is hit, this.key is "type", this.parent.key is "paths" but this.keys is null and thats why the null exception. I guess you wanted this validation to be run only when traversing paths=endpoints, not some paths property.
Some more strict check should be made to make sure it's only executed when it's on the "first-level" paths, e.g.:

this.parent.path.length === 1  && this.parent.path[0] === 'paths' // this.parent.path === ['paths']

Issues with cookie parameters being excluded from formatted document

Seems that components->parameters->cookies are not supported. In fact, if you add a parameter with in: cookie, the parameter is not included in the output. That is a bit of a head scratcher.

Supported in version 3.0.3
https://swagger.io/docs/specification/describing-parameters/#cookie-parameters

"components": { "parameters": { "JSESSIONID": { "name": "JSESSIONID", "in": "cookie", "required": false, "schema": { "type": "string" } } } }

Make test.js easier to maintain

Currently the test.js file is a mess and not easy to use.

I should try to test.js script easier to maintain by using the configFile and re-use the CLI functions.

1.15.4 fails to locate the filter file path when set

With the latest version, 1.15.4, using the --filterFile parameter, it produces the following error.
"Filter file error - no such file or directory"
We have tried it both with the relative path and an absolute path to the file within our CI pipeline with the same results.
The contents of our file (named filter.json) is the following and have verified that it exists and has the output below.
stripFlags: ['x-internal']
We altered our CI pipeline to install the prior version (and not pull the latest) and that solves it currently.
`npm install -g [email protected]

examples with properties named "schemas" are rewritten to an object

I have an api endpoint like this:

           "CreateGroupRequest": {
                "example": {
                    "displayName": "Test SCIM",
                    "members": [],
                    "schemas": [
                        "urn:ietf:params:scim:schemas:core:2.0:Group"
                    ]
                },
                "properties": {
                    "displayName": {
                        "type": "string"
                    },
                    "externalId": {
                        "type": "string"
                    },
                    "members": {
                        "items": {
                            "$ref": "#/components/schemas/ScimResource"
                        },
                        "type": "array"
                    },
                    "schemas": {
                        "items": {
                            "type": "string"
                        },
                        "type": "array"
                    }
                },
                "required": [
                    "displayName"
                ],
                "title": "CreateGroupRequest",
                "type": "object"
            },

After running this through openapi-format, the example is rewritten like so:

        "example": {
          "displayName": "Test SCIM",
          "members": [],
          "schemas": [
            {
              "0": "u",
              "1": "r",
              "2": "n",
              "3": ":",
              "4": "i",
              "5": "e",
              "6": "t",
              "7": "f",
              "8": ":",
              "9": "p",
              "10": "a",
              "11": "r",
              "12": "a",
              "13": "m",
              "14": "s",
              "15": ":",
              "16": "s",
              "17": "c",
              "18": "i",
              "19": "m",
              "20": ":",
              "21": "s",
              "22": "c",
              "23": "h",
              "24": "e",
              "25": "m",
              "26": "a",
              "27": "s",
              "28": ":",
              "29": "c",
              "30": "o",
              "31": "r",
              "32": "e",
              "33": ":",
              "34": "2",
              "35": ".",
              "36": "0",
              "37": ":",
              "38": "G",
              "39": "r",
              "40": "o",
              "41": "u",
              "42": "p"
            }
          ]
        },

Could this be due to some kind of recursive handling of the open api "schemas" field? Thanks in advance for taking a look.

sort - order request parameters by name

I couldn't figure out how to do this.
I need the get, post etc. request parameters to be ordered by the value of the name field.
The parameter fields themselves are ordered consistently according to the config but I'd like the the parameter ordering itself to be alphabetical.

    "/api/products": {
      "get": {
        "summary": "Get the list of existing products.",
        "parameters": [
          {
            "name": "offset",    _this should be the second one_
            "in": "query",
            "description": "The offset to apply to the paginated query.",
            "required": false,
            "default": 0,
            "format": "int32",
            "minimum": 0,
            "type": "integer"
          },
          {
            "name": "limit",        _l comes before o, this should be the first one_
            "in": "query",
            "description": "The limit to apply to the paginated query.",
            "required": false,
            "default": null,
            "format": "int32",
            "maximum": 100,
            "minimum": 0,
            "type": "integer",
            "x-nullable": true
          }
        ],

Skip sorting the HTTP response code

Currently openapi-format also seems to format the HTTP response code in the OpenAPI document.
It would be best not to sort them and leave the order as is.

a "properties" field in the properties cause for splitting of the word

If you have property named "properties" in the properties object, it converts the object.

OpenAPI

components:
  schemas:
    operationsResultData:
      type: object
      properties:
           properties:
                 type: object

results in

components:
  schemas:
    operationsResultData:
      type: object
      properties:
               properties:
                      type:
                      '0': o
                      '1': b
                      '2': j
                      '3': e
                      '4': c
                      '5': t

Inverse flags

Hi, I was wondering if we can implement inverse flags as well?
Thank you

Keep $ref dereference when writing the update files

Currently, openapi-format dereferences the OpenAPI documents to do its formatting, sorting, ... and write a dereferenced result.

Investigate the option to leverage: https://www.npmjs.com/package/json-refs to format the OpenAPI documents and update the $ref values in different files.

const jsonRefs = require('json-refs');

const json = {
  "foo": {
    "$ref": "#/bar"
  },
  "bar": {
    "baz": "qux"
  }
};

const options = {
  filter: ['relative', 'remote'],
  loaderOptions: {
    processContent: (res, callback) => callback(undefined, res.text)
  }
};

jsonRefs.resolveRefs(json, options).then(
  (results) => {
    // make changes to the resolved object
    results.resolved.bar.baz = "newValue";
    // write the changes to the $ref locations
    jsonRefs.updateRefs(results.refs, results.resolved).then(
      (updated) => console.log(updated),
      (err) => console.log(err)
    );
  },
  (err) => console.log(err)
);

Suggestion: inverse filter

Hi,

I really love your tool. Especially, the sort options are very valuable in creating an easy diffable open api specification!

Still, there is one feature I am missing: an inverse filter option.

I don't want to have all of my operations in specification. Of course, I could use the already existing filter per operationId. Unfortunately, there are way more operations don't want to have in my specification than I want to have.

Now, I would have to add all operations to the filter, except the ones that should remain. Plus each time, I add a new operation, I would need to touch the filter file again.

Having an inverse filter would make my live much easier.

What do you think? Would it be possible add this option to openapi-format?

Best

Christian

some needed objects are filtered out when using inverseTags with unusedComponents

Hello Tim,
I'm using your wonderfull tool to extract few interfaces from a big openapi file using inverseTags and unusedComponents filter.
Unfortunately it looks like there are some used objects also removed. I don't know whether my filter is somehow wrong or whether this is a bug. Would be great if you could have a look.
My command line is: openapi-format input.json -f filter.yaml --json -vvv -o output --no-sort
I'll attach the source file, filter and output file as well as expected output.
Enjoy your day

Markus

output.json
filter.yaml.txt
[Output(expected).json](https://github.com/thim81/openapi-format/files/14978738/Output.expect
input.json
ed.json)

error with inverseOperationIds and example values of null

An error is thrown if filter option "inverseOperationIds" is used against a json schema file that contains a null value in any of the examples (not necessarily in the operation with the to-be-filtered operationID). Obviously, I was able to fix this by adjusting the example value, but it took me a while to identify the issue, so it'd be great if this error could be caught with a better description than UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'operationId' of null.

The problematic part in the json:
"primaryColor": { "type": "string", "example": null }

Restrict casing of operationId

The operationId casing should only be applied in the "path" object, and not in "examples".

sample-script-output-failure:
      value:
        operationId: 7e24fadb-c31a-4b47-a8bf-4996900fc6c9
        created: '2020-06-19T12:01:03.456Z'
        lastAction: '2020-06-19T12:06:03.456Z'

filtering unused components - not working

Hi,

I am trying to filter a yaml openapi spec, to remove a path and remove unused schema components.
The path filtering works fine, but the unused component removal does not work - unless I deliberately add an unused component to the original file (I did this by accident while experimenting)

Please see attached zip file for sample files and README.md with steps to reproduce issue
I will also copy in README.md below

There is always the possibility that I am doing something wrong - apologies if that is the case here.

Thanks,

Connor

Mac OS
openapi-format version: tried with 1.14.0 and 1.17.0 - same results

PROBLEM: The 'remove unused components' doesn't work - it leaves some items in there that it shouldn't

Steps to show problem:

  1. edit spec: pet-sample-openapi-spec.yaml
    observe it has 2 paths, each path references a response schema object which uses a second schema object
  2. filter the spec by running: ./dev-produce-filtered-spec.sh
    this uses "dev-produce-filtered-spec_customFilter.yaml" which only includes one of the paths (WORKS) but should removed unused "schemas" (DOESNT WORK)
  3. edit result: pet-sample-openapi-spec_filtered.yaml
    observe it includes only one path (correct), but all the schema objects are included - some of which are unused so should have been removed
  4. edit spec 2: pet-sample-openapi-spec-2.yaml
    observe it is the same as the first spec, but it has an unused component in schemas: ThisTypeIsNeverReferencedAnywhere
  5. filter the spec 2 by running: ./dev-produce-filtered-spec-2.sh
    Note: In the output it says it's removed some unused components
  6. edit result: pet-sample-openapi-spec_filtered-2.yaml
    observe the filtering has now worked - one path and all unused components have been removed

Archive.zip

sort - order not always preserved on certain sub-objects

My goal is to create normalised openapi.json files which developers can confidently review in a PR before deploying to apigee. This tool seems promising in helping us achieve that.

Unfortunately I'm experiencing unexpected sort side-effects which run contrary to the described behaviour:

The fields that are not specified will keep their order like it is in the original OpenAPI document, so only defined fields will be re-ordered.

Just using the default sorting, sub-properties eg auditStatus seem to have a reverse-alpha sort applied. Is there a way to configure that (other than essentially declaring the entire schema ordering in the config file, right down to the leaf level)?

Input:

            "schema": {
              "items": {
                "properties": {
                  "auditStatus": {
                    "readOnly": true,
                    "type": "string"
                  },
                  "columnType": {
                    "type": "string"
                  },
                  "createdBy": {
                    "readOnly": true,
                    "type": "string"
                  },
                  "createdDate": {
                    "format": "date-time",
                    "readOnly": true,
                    "type": "string"
                  },
                  "customValidationType": {
                    "type": "string"
                  },
                  "dataContractColumnValidations": {
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        },
                        "customValidationId": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "dataContractColumnId": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "id": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "lastModifiedBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "lastModifiedDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        }
                      },
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "description": {
                    "type": "string"
                  },
                  "id": {
                    "format": "int32",
                    "readOnly": true,
                    "type": "integer"
                  },
                  "isActive": {
                    "type": "boolean"
                  },
                  "lastModifiedBy": {
                    "readOnly": true,
                    "type": "string"
                  },
                  "lastModifiedDate": {
                    "format": "date-time",
                    "readOnly": true,
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "parameterType": {
                    "type": "string"
                  },
                  "rule": {
                    "type": "string"
                  },
                  "scalarModelContractValidations": {
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "createdDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        },
                        "customValidationId": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "id": {
                          "format": "int32",
                          "type": "integer"
                        },
                        "lastModifiedBy": {
                          "readOnly": true,
                          "type": "string"
                        },
                        "lastModifiedDate": {
                          "format": "date-time",
                          "readOnly": true,
                          "type": "string"
                        },
                        "scalarModelContractId": {
                          "format": "int32",
                          "type": "integer"
                        }
                      },
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              },
              "type": "array"
            }
          },

Output:

            "schema": {
              "type": "array",
              "items": {
                "properties": {
                  "auditStatus": {
                    "type": "string",
                    "readOnly": true
                  },
                  "columnType": {
                    "type": "string"
                  },
                  "createdBy": {
                    "type": "string",
                    "readOnly": true
                  },
                  "createdDate": {
                    "type": "string",
                    "format": "date-time",
                    "readOnly": true
                  },
                  "customValidationType": {
                    "type": "string"
                  },
                  "dataContractColumnValidations": {
                    "type": "array",
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        },
                        "customValidationId": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "dataContractColumnId": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "id": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "lastModifiedBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "lastModifiedDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        }
                      },
                      "type": "object"
                    }
                  },
                  "description": {
                    "type": "string"
                  },
                  "id": {
                    "type": "integer",
                    "format": "int32",
                    "readOnly": true
                  },
                  "isActive": {
                    "type": "boolean"
                  },
                  "lastModifiedBy": {
                    "type": "string",
                    "readOnly": true
                  },
                  "lastModifiedDate": {
                    "type": "string",
                    "format": "date-time",
                    "readOnly": true
                  },
                  "name": {
                    "type": "string"
                  },
                  "parameterType": {
                    "type": "string"
                  },
                  "rule": {
                    "type": "string"
                  },
                  "scalarModelContractValidations": {
                    "type": "array",
                    "items": {
                      "properties": {
                        "auditStatus": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "createdDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        },
                        "customValidationId": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "id": {
                          "type": "integer",
                          "format": "int32"
                        },
                        "lastModifiedBy": {
                          "type": "string",
                          "readOnly": true
                        },
                        "lastModifiedDate": {
                          "type": "string",
                          "format": "date-time",
                          "readOnly": true
                        },
                        "scalarModelContractId": {
                          "type": "integer",
                          "format": "int32"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "type": "object"
              }
            }
          },

Components with period in their names are removed unconditionally with the unusedComponents filter option.

If a key under the fixed fields in the components object (in a descriptor) has a period, the key is removed from the descriptor after filtering with the unusedComponents option. For example:

filter.json

{

    "unusedComponents": [
        "examples"
    ]
}

descriptor.yaml

# . . .

      responses:
        '200':
          content:
            application/json:
              examples:
                tokenResponse:
                  $ref: '#/components/examples/Id.Token'
# . . .
components:
  examples:
    Id.Token:
# . . .

After filtering, the reference will remain, but the key in the components object will be removed.

If I read the spec correctly, periods are allowed in the key names; from https://spec.openapis.org/oas/v3.0.3#components-object:

All the fixed fields declared above are objects that MUST use keys that match the regular expression: ^[a-zA-Z0-9.-_]+$.

var regex = /^[a-zA-Z0-9\.\-_]+$/;
var key = 'Id.Token';
key.match(regex); // > [ "Id.Token" ]

Issue with InverseOperationId while parsing Free-Form object.

Describe the bug
The free-form object described in our yaml file gets lost when applying the InverseOperationId filter to various operations.

To Reproduce
Steps to reproduce the behavior:

  1. Created an openapi.yaml file.
openapi: 3.0.2
info:
  title: OpenSearch
  version: '2021-11-23'
paths:
  /_cat/indices:
    get:
      description: 'Returns information about indices: number of primaries and replicas, document counts, disk size, etc.'
      operationId: GetCatIndices
      parameters:
        - name: bytes
          in: query
          schema:
            type: number
            nullable: true
        - name: expand_wildcards
          in: query
          schema:
            $ref: '#/components/schemas/ExpandWildcards'
        - name: health
          in: query
          schema:
            $ref: '#/components/schemas/HealthStatus'
        - name: include_unloaded_segments
          in: query
          schema:
            type: boolean
            nullable: true
        - name: pri
          in: query
          schema:
            type: boolean
            nullable: true
        - name: master_timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
        - name: timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
      responses:
        '200':
          description: GetCatIndices 200 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCatIndicesOutputPayload'
  '/_cat/indices/{index}':
    get:
      description: 'Returns information about indices: number of primaries and replicas, document counts, disk size, etc.'
      operationId: GetCatIndicesWithIndex
      parameters:
        - name: index
          in: path
          schema:
            type: string
            pattern: '^[^+_\-\.][^\\, /*?"<>| ,#\nA-Z]+$'
          required: true
          example: books
        - name: bytes
          in: query
          schema:
            type: number
            nullable: true
        - name: expand_wildcards
          in: query
          schema:
            $ref: '#/components/schemas/ExpandWildcards'
        - name: health
          in: query
          schema:
            $ref: '#/components/schemas/HealthStatus'
        - name: include_unloaded_segments
          in: query
          schema:
            type: boolean
            nullable: true
        - name: pri
          in: query
          schema:
            type: boolean
            nullable: true
        - name: master_timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
        - name: timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
      responses:
        '200':
          description: GetCatIndicesWithIndex 200 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCatIndicesWithIndexOutputPayload'
components:
  schemas:
    ExpandWildcards:
      type: string
      enum:
        - all
        - open
        - closed
        - hidden
        - none
    GetCatIndicesOutputPayload: {}
    GetCatIndicesWithIndexOutputPayload: {}
    HealthStatus:
      type: string
      enum:
        - green
        - yellow
        - red

  1. Created a InverseOperationId filter in customFilter.json file.
{
    "inverseOperationIds": ["GetCatIndicesWithIndex"]
}
  1. Command used: openapi-format openapi.yaml -o catindices_filtered.yaml -f customFilter.json
  2. Content of resultant file (catindices_filtered.yaml ).
openapi: 3.0.2
info:
  title: OpenSearch
  version: '2021-11-23'
paths:
  '/_cat/indices/{index}':
    get:
      operationId: GetCatIndicesWithIndex
      description: 'Returns information about indices: number of primaries and replicas, document counts, disk size, etc.'
      parameters:
        - name: index
          in: path
          required: true
          schema:
            type: string
            pattern: '^[^+_\-\.][^\\, /*?"<>| ,#\nA-Z]+$'
          example: books
        - name: bytes
          in: query
          schema:
            type: number
            nullable: true
        - name: expand_wildcards
          in: query
          schema:
            $ref: '#/components/schemas/ExpandWildcards'
        - name: health
          in: query
          schema:
            $ref: '#/components/schemas/HealthStatus'
        - name: include_unloaded_segments
          in: query
          schema:
            type: boolean
            nullable: true
        - name: pri
          in: query
          schema:
            type: boolean
            nullable: true
        - name: master_timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
        - name: timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
      responses:
        '200':
          description: GetCatIndicesWithIndex 200 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCatIndicesWithIndexOutputPayload'
components:
  schemas:
    ExpandWildcards:
      type: string
      enum:
        - all
        - open
        - closed
        - hidden
        - none
    HealthStatus:
      type: string
      enum:
        - green
        - yellow
        - red

Issue: Free-form object GetCatIndicesWithIndexOutputPayload: {} is getting skipped.

Expected behavior
After using InverseOperationId filter resultant file should be:

openapi: 3.0.2
info:
  title: OpenSearch
  version: '2021-11-23'
paths:
  '/_cat/indices/{index}':
    get:
      description: 'Returns information about indices: number of primaries and replicas, document counts, disk size, etc.'
      operationId: GetCatIndicesWithIndex
      parameters:
        - name: index
          in: path
          schema:
            type: string
            pattern: '^[^+_\-\.][^\\, /*?"<>| ,#\nA-Z]+$'
          required: true
          example: books
        - name: bytes
          in: query
          schema:
            type: number
            nullable: true
        - name: expand_wildcards
          in: query
          schema:
            $ref: '#/components/schemas/ExpandWildcards'
        - name: health
          in: query
          schema:
            $ref: '#/components/schemas/HealthStatus'
        - name: include_unloaded_segments
          in: query
          schema:
            type: boolean
            nullable: true
        - name: pri
          in: query
          schema:
            type: boolean
            nullable: true
        - name: master_timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
        - name: timeout
          in: query
          schema:
            type: string
            pattern: '^([0-9]+)(?:d|h|m|s|ms|micros|nanos)$'
      responses:
        '200':
          description: GetCatIndicesWithIndex 200 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCatIndicesWithIndexOutputPayload'
components:
  schemas:
    ExpandWildcards:
      type: string
      enum:
        - all
        - open
        - closed
        - hidden
        - none
    GetCatIndicesWithIndexOutputPayload: {}
    HealthStatus:
      type: string
      enum:
        - green
        - yellow
        - red

ConvertTo: downgrade 3.1 to 3.0

Hi! I tries to use this package to downgrade a 3.1 spec file to a 3.0 one. That result in success, but the file is still in 3.1.
I doing something wrong or this is not supported?

npx openapi-format openapi.yaml -o openapi3.json --convertTo "3"
==============================================================================
OpenAPI-Format CLI settings:
- Sort file:            (defaultSort.json)
- Input file:           openapi.yaml
- Output file:          openapi3.json
==============================================================================
โœ…  OpenAPI formatted successfully
==============================================================================

Some filtered fields are still present after formatting

I have this definition below:

/payment_requests:
    post:
      tags:
        - public
      operationId: CreatePaymentRequest
      summary: Create Payment Request
      description: Create Payment Request
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
          x-internal-field: true
        - $ref: '#/components/parameters/BusinessID'
          x-internal-field: true
        - $ref: '#/components/parameters/CallbackURL'
          x-internal-field: true
        - $ref: '#/components/parameters/ServiceID'
          x-internal-field: true

And after running formatting, it resulted this:

/payment_requests:
    post:
      operationId: CreatePaymentRequest
      summary: Create Payment Request
      description: Create Payment Request
      parameters:
        - $ref: '#/components/parameters/BusinessID'
          x-internal-field: true
        - $ref: '#/components/parameters/ServiceID'
          x-internal-field: true

Filter: "flags": ["x-internal-field"]

As you can see there are 2 field that are left out. I was wondering if anyone knows how to fix it? I've been trying to debug it & reconfiguring my openapi spec file but still no luck

YAML empty objects get sripped away

I've experienced that empty objects in the yaml gets stripped away. An example for a request body in openapi with an epmty object gets stripped away.

E.g.

example:
  default:
    key1: "value1"
    key: {}

becomes

example:
  default:
    key1: "value1"

Is this related to the parsing library used in openapi-format? Do you have any suggestions how to preserve the empty object?

yaml document start characters `---` & comments not preserved

Hi ๐Ÿ‘‹

First of all thanks for developing this awesome lib!

I am using the openapi-format more like a validator (mainly because it removes comments like mentioned in #44), not as a formatted, and in some projects, we are using --- (a YAML document start sign - as described in 2.2 Structure), but running the openapi-format on such documents produces output without --- and it would be nice to preserve --- when it's present or add some option to always add/remove it from the file.

PS. https://github.com/thim81/asyncapi-format also does not preserve ---

Transformation of Number

Hi @thim81, we've seen that latest version, specifically this commit, is affecting numbers used in escaped values.

As an example, we use a vendor extension in our specs:

      x-typescript-params: |-
        {
          id: 'id_example',
          payment: {
            currency: 'USD',
            currency_rate: 0.69,
            total_amount: 49.99,
            reference: '123456',
            payment_method: 'Credit Card',
            payment_method_reference: '123456'            
        }

Running 1.10.0 results is the following:

      x-typescript-params: |-
        {
          id: 'id_example',
          payment: {
            currency: 'USD',
            currency_rate: '0.69===',
            total_amount: '49.99===',
            reference: '123456',
            payment_method: 'Credit Card',
            payment_method_reference: '123456'            
        }

Maybe an edge case, but thought you should know

Node 12 Support broken

With commit 56713e7 this library started using more modern language features.

This causes problems when running the library on node 12

Reproduction:

# set node version 12
nvm use 12
# download petstore example
curl https://petstore3.swagger.io/api/v3/openapi.json --output ./tmp/docs-json 
# use library to convert
npx openapi-format ./tmp/docs-json

This result in the Error: Unexpected token '.' (To be exact bin/cli.js:143 cliLog.unusedComp = resFilter?.resultData?.unusedComp;

Doing the above on node 14 works flawlessly.

I would advise to specify the engines option in package.json and then install a compiler like Babel or sth. similar for easy compatibility with older node versions

In the meantime the workaround is to use node 14

Format: Generate OAS properties like operationId

Use-case:
Some OAS properties can be considered wanted (or even required).
A typical property is operationId , instead of reviewing all the paths if they have a missing operationId; openapi-format could insert the ones missing AND correct the casing of the value.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.