Surnet/swagger-jsdoc

Can't Reference Anchors from Within Another Anchor

Opened this issue ยท 0 comments

Is your feature request related to a problem? Please describe.
I'm currently investigating swagger-jsdoc as potential solution for auto-generating my openapi spec.

One of the hard requirements I have is that my API is versioned, and there are occasions where a handler might be used across multiple versions.

I've been able to get this to work as a proof of concept with a simple /healthz endpoint, an example of this is below.

The problem
While the below example works, I am finding that it's a bit inflexible. Following the examples here I was hoping to define a directory of properties that could be referenced from my handler definitions. However, attempting to reference any anchors from within my templates ends up returning a null value.

For example the following spec

/**
 * @openapi
 * /v3/healthz:
 *   get: *getHealthzV3
 */
export const getHealthz = (_req, res) => {
    res.json({
        status: '๐Ÿ˜Ž Alriiight'
    })
}

/**
 * @openapi
 * x-template:
 *   get: &getHealthzV3
 *     description: Find out if the service is healthy and coooool
 *     responses:
 *       '200':
 *         description: OK - API is healthy
 *         content:
 *           text/plain:
 *             schema:
 *               type: object
 *               properties:
 *                 status: *healthStatus
 *             examples:
 *               healthyResponse:
 *                 summary: A healthy API response
 *                 value: '๐Ÿ˜Ž Alriiight'
 */

/**
 * @openapi
 * x-template:
 *   healthStatus: &healthStatus
 *     type: string
 *     description: The Servers Status
 *     enum:
 *       - OK
 *       - DEAD
 */

will generate

{
  "openapi": "3.1.0",
  "info": {
    "title": "Test",
    "version": "v3.0.0"
  },
  "paths": {
    "/healthz": {
      "get": {
        "description": "Find out if the service is healthy and coooool",
        "responses": {
          "200": {
            "description": "OK - API is healthy",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": null
                  }
                },
                "examples": {
                  "healthyResponse": {
                    "summary": "A healthy API response",
                    "value": "๐Ÿ˜Ž Alriiight"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Further example of my overall goals in this design below:

// versionSelectionMiddleware inspects headers to determine if this handler is valid for this request
// otherwise it cascades to the next handler 
/**
 * @openapi
 * /v1/healthz:
 *   get: *getHealthzV1
 *
 * /v2/healthz:
 *   get: *getHealthzV1
 */
router.get('/', versionSelectionMiddleware('v1', 'v2'), getHealthz.V1)

/**
 * @openapi
 * /v3/healthz:
 *   get: *getHealthzV3
 */
router.get('/', versionSelectionMiddleware('v3'), getHealthz.V3)

Ultimately I suppose I just have two questions:

  1. Is this a bug? Are you supposed to be able to reference anchors from within other anchors?
  2. Is this the correct approach? Or would this be something that would make more sense to references as components instead of as anchors?