Skip to content

Latest commit

 

History

History
337 lines (266 loc) · 11.7 KB

directives.md

File metadata and controls

337 lines (266 loc) · 11.7 KB

Directives

Directives are used to tweak the generated code prior to generation, and are included in your configuration file (usually a README file). For example, if you want to change a property's name from the name defined in the OpenAPI definition, you can add a directive in your readme to accomplish this.

We usually recommend changing the swagger before going the directive route, but if you'd like the original swagger to remain untouched (for example, you want to rename the generated model in the Python SDK, but not in other SDKs), directives are the route for you.

Stylistic note: we recommend annotating your directives in your config file with a header about what the directive is doing.

Structure and Terminology

Directives consist of three parts:

  • Location: denoted by the field from, which document are we trying to transform. For swagger transformations, it's always from: swagger-document.

  • Filter: denoted by the field where, contains the criteria to select the object.

    • An operation is filtered by
      • its path in the swagger's paths object AND
      • it's HTTP verb
    • A parameter is filtered by:
      • its location in its operation (see above) OR
      • its name in the swagger's parameters object, if it's defined as a common parameter there (see the Common Parameters for Various Paths section here for more information)
    • A model can be filtered by:
      • its name in the components or definitions section OR
      • its location in its outer object, if defined within another object OR
      • its location in an operation, if defined within an operation
    • A property can be filtered by:
      • its location within its parent object
  • Transform: denoted by the field transform, the actions we would like to be applied on the specified objects. The list of available variables and functions can be found in eval.ts

Built-in Directives

See built in directives here

Debug a directive

JsonPath.com

To make sure the where clause is defined correctly you can use https://jsonpath.com to verify all the elements wanted are selected. Usage:

  1. Paste where clause in the JSONPath Syntax input
  2. Paste spec in the Inputs section
  3. Evaluation result should be an array of all the object that were matched with the given path.

NOTE: The library used in this website is slightly different and there could be inconsistency for some edge cases. You can use the next section to debug the issue and check if autorest is selecting the same elements.

debug flag

Directive provide a debug field that will enable verbose logging of the directive run.

Example:

directive:
  - from: swagger-document
    where: $.paths
    debug: true
    transform: |
      $["x-abc"] = true

$lib.log function

Along with some other available function to the transform context(See eval.ts) $lib.log lets you log.

directive:
  - from: swagger-document
    where: $.paths
    transform: |
      $lib.log($);
      $["x-abc"] = true

Use directive to permanently update inputs

Directives lets you modify the input files on the fly but there might be cases where you just want to fix the input files intead of patching it JIT. For that you can run autorest with the --apply-transforms-in-place. This will take all the directives meant to be run on the Swagger 2.0 or OpenAPI 3.0 files and update the files themself.

# Apply transforms defined in the mytransforms.md config file to the openapi.yaml file.
autorest --apply-transforms-in-place --input-file=openapi.yaml --require=./mytransforms.md

# Apply transforms defined in the mytransforms.md config file to all the input files reference in the readme config.
autorest --apply-transforms-in-place --require=./mytransforms.md ./readme.md

Directive Scenarios

The following directives cover the most common tweaking scenarios for generation. Most of those have a built-in directive helper and are shown here as examples.

Operation Rename

A common use case is renaming an operation. Say you have the following operation in your swagger:

...
"paths": {
    "/vm": {
        "get": {
            "operationId": "getVirtualMachine",
            ...
        }
    }
    ...
}

and you'd like to rename it from getVirtualMachine to getVM. You would refer to this operation with the combination of its path and its http verb. As always, you use from: swagger-document to specify you're changing your swagger document. Finally, what you're transforming is the "operationId". Putting this together, your directive looks like:

### Directive renaming operation from "getVirtualMachine" to "getVM"
directive:
  from: swagger-document
  where: '$.paths["/vm"].get'
  transform: >
    $["operationId"] = "getVM";

Parameter Rename

To select the parameter, you either refer to its location inside the operation it's defined within, or its name in the common parameters section. We'll go over both in this example. In both cases, we'll be looking to rename parameter id to identifier.

Parameter defined in operation

...
"paths": {
    "/vm": {
        "get": {
            "operationId": "getVirtualMachine"
            "parameters": [
                {
                    "name": "id",
                    ...
                }
            ]
        }
    }
    ...
}

Referring to the parameter's location in the operation, our filter would be where: '$.paths["/vm"].get.parameters[0]'. We're changing the name of the parameter, so you could apply your transform to the name field. However, it's better to change the x-ms-client-name field instead, since there could be this field defined for your parameter, and this field overrides the name field. This becomes

### Directive renaming "getVirtualMachine"'s parameter "id" to "identifier".
directive:
  from: swagger-document
  where: '$.paths["/vm"].get.parameters[0]'
  transform: >
    $["x-ms-client-name"] = "identifier";

Parameter defined in the "Parameters" section

---
"parameters": { "Id": { "name": "id", ... } }

Now, we refer to the parameters location within the swagger's parameters object. This changes our filter to where: '$.parameters["Id"]', and leads us to the following directive:

### Directive renaming "getVirtualMachine"'s parameter "id" to "identifier".
directive:
  from: swagger-document
  where: '$.parameters["Id"]'
  transform: >
    $["x-ms-client-name"] = "identifier";

Model Rename

We have the following swagger:

...
"definitions": {
    "VM": {
        "type": "object"
        ...
    }
    ...
}

and we'd like to rename the model VM to VirtualMachine. We refer to the model with filter where: #.definitions.VM. Since the location we're trying to transform is listed as a key in the swagger dictionary and not a field, we change the model's name by adding in field x-ms-client-name. Thus, our directive looks like

### Directive renaming "VM" model to "VirtualMachine"
directive:
  from: swagger-document
  where: "$.definitions.VM"
  transform: >
    $["x-ms-client-name"] = "VirtualMachine";

Property Rename

Let's say we want to rename the following property from id to identifier.

...
"definitions": {
    "VM": {
        "type": "object"
        "properties": {
            "id": {
                ...
            }
        }
    }
    ...
}

We refer to the property based on its location in its parent object, giving us filter where: #.definitions.VM.properties.id. Similar to a model, we have to use x-ms-client-name since there's no name field to change. This gives us

### Directive renaming "id" property to "identifier"
directive:
  from: swagger-document
  where: "$.definitions.VM.properties.id"
  transform: >
    $["x-ms-client-name"] = "identifier";

Enum Value Rename

Renaming an enum requires referencing the x-ms-enum used to define the enum. In this scenario, we're looking to change the name of an enum value from AzureVM to AzureVirtualMachine. As you can see from the swagger:

...
"definitions": {
    "VM": {
        "type": "object"
        "properties": {
            "virtualMachineType": {
                "type": "string",
                "enum": [
                    "Azure_VM",
                    ...
                ],
                "x-ms-enum": {
                    "name": "VirtualMachineTypes",
                    "values": [
                        {
                            "value": "Azure_VM"
                            "name": "AzureVM"
                            ...
                        },
                        ...
                    ]
                }
            }
        }
    }
    ...
}

This gives us directive

### Directive renaming enum AzureVM to AzureVirtualMachine
directive:
  from: swagger-document
  where: "$.definitions.VM.properties.virtualMachineType.x-ms-enum.values[0]"
  transform: >
    $["x-ms-client-name"] = "AzureVirtualMachine";

Now, we would access the enum through VirtualMachineTypes.AzureVirtualMachine instead of VirtualMachineTypes.AzureVM.

Change Description

Changing a description is very similar whether you're changing an operation's description or a model's description etc. The only thing that varies is how to refer to the object whose description your changing. Since this is covered in the previous examples, we won't do separate sections for this. Instead, we will show you how to change a property's description, which can be easily extended to another object, i.e. an operation.

Let's say we renamed the property from id to identifier, and we want to change all references in the description of id to identifier:

...
"definitions": {
    "VM": {
        "type": "object"
        "properties": {
            "id": {
                "description": "The 'id' property is used to identify your VM instance.
            }
        }
    }
    ...
}

We once again refer to the property's location as where: #.definitions.VM.properties.id, and we want to change the description field in the property. This gives uss

### Directive changing references of 'id' to 'identifier' in the 'identifier' property's description
directive:
  from: swagger-document
  where: "$.definitions.VM.properties.id"
  transform: >
    $["description"] = $["description"].replace("'id'", "'identifier'");

For language-specific directives, see the ones for: