Search code examples
ramlraml-1.0

How can a resourceType inherit from multiple types?


Goal: create resourceTypes for CRUD endpoints without repeating myself.

(working with RAML 1.0 in Anypoint Studio and Mulesoft Design Center)

Let's start a couple resourceTypes for single action endpoints:

resourceTypes:
  getItem:
    get: 
      responses:
            200:
              body:
                application/json
  postItem:
    post:
      responses:
        201:
          body: null
  deleteItem:
    delete:
      responses:
        200:
          body: null 

So far, so good.

Now I want to create a resourceType for an endpoint that allows both GET and DELETE requests. This is valid:

  getDeleteItem:
    type: getItem
    delete:
      responses:
        200:
          body: null

... but I had to repeat the code from deleteItem, which I don't like.

These approaches do not work:

# the syntax for a union of types, does not work for resourceTypes
  getDeleteItem:
    type: getItem | deleteItem
# no error here, but everything after the first type reference is ignored
  getDeleteItem:
    type: { getItem, deleteItem }

Is there a better way?

I came up with an ugly workaround ("base" resourceTypes that each have their type set to a variable, so they can be strung together), but it seems to cause inconsistent errors and crashes in Mulesoft Design Center.


Solution

  • I did eventually find a clean answer to this: use optional methods (verbs).

    Instead of the original 3 resourceTypes, create one with all 3 verbs. Mark each verb as required: false or append a question mark to the verb name.

    resourceTypes:
      myResourceType:
        get?: 
          responses:
                200:
                  body:
                    application/json
        post?:
          responses:
            201:
              body: null
        delete?:
          responses:
            200:
              body: null 
    

    Use the resourceType at your endpoint as normal, and add a line under the endpoint for each verb you want to use.

    This example creates an endpoint called "myResource" that accepts GET and POST requests, but does not accept DELETE requests.

    /myResource:
      type:
        myResourceType
      get:
      post:
    

    The GET and POST inherit everything we defined in the resourceType. We are free to override or add to each verb at the endpoint.

    You could also create additional resourceTypes with this one as a root type, but I found issues when attempting to use variables with inherited resourceTypes, and optional methods seem flexible enough to meet my goals.