Redocly/redocly-cli

The remove-x-internal decorator does not fully remove internal paths which contain a path-level parameter

Opened this issue · 3 comments

Describe the bug

Right now if an x-internal path has a path-level parameter, the path does not get fully removed.
If the path is defined on the operation level (under post), the entire path is removed, as expected.

This might be a regression, we've had such paths before, and have been using the CLI since the beta days to remove them. However, I can't be certain.

To Reproduce

openapi.yaml:

paths:
  '/products/{product_id}/clowncopterize':
    parameters:
      - $ref: '#/components/parameters/ProductID'
    post:
      summary: Clowncopterize product
      description: Clowncopterizes the given product.
      operationId: product-clowncopterize
      x-internal: true
      tags:
        - Products
      responses:
        '204':
          description: OK

Result (redocly bundle openapi.yaml):

paths:
  /products/{product_id}/clowncopterize:
    parameters:
      - $ref: '#/components/parameters/ProductID'

My example uses $ref, but the same behavior is present if the parameter is defined directly.

Repo with full example: https://github.com/bojanz/cli-bug

Expected behavior

The entire path is removed.

Redocly Version(s)

1.19.0

Node.js Version(s)

v20.12.2

Hi @bojanz! I'm not sure it's a bug as the decorator removes exactly what you've told it to remove. Technically, x-internal could be placed on any node, so it'd be quite challenging to figure out the context and clean up it appropriately.
In your case I'd recommend using a custom decorator in addition to the existing one to remove the empty path items. You'll need to create a plugin for that:

my-plugin.js:

module.exports = {
  id: 'test',
  decorators: {
    oas3: {
      'cleanup-paths': () => ({
        Paths: {
          leave: (paths) => {
            for (const pathName in paths) {
              console.log(paths[pathName]);
              // Check if we can remove the path
              if (/* the path is empty... */) {
                delete paths[pathName];
              }
            }
          },
        },
      }),
    },
  },
};

Then use it in redocly.yaml:

plugins:
  - ./my-plugin.js # <- reference the filepath to your plugin here
decorators:
  remove-x-internal: on
  test/cleanup-paths: on # <- use the decorator

Please let me know if that helps.

I totally get the argument for keeping the remove-x-internal decorator simple, since it currently doesn't care about which level it is operating on.

Perhaps it would make sense to add a separate decorator that removes paths with no operations? The two could then be combined to get the result expected by some users.

I’d like to add one, but I don’t have the bandwidth at the moment. If you'd like, you can try adding the decorator yourself here, or contribute to our Cookbook.