redocly-cli icon indicating copy to clipboard operation
redocly-cli copied to clipboard

bundle command resolves refs from external files to a component name using underscore as separator

Open mishabruml opened this issue 1 year ago • 10 comments

In the case where components with the same key are imported (referred) from different files, then the filename is prefixed to the object key (to avoid collision) but the prefix is separated with a _.

Describe the bug

When bundling swagger with complex references, referring to objects keyed with the same key from external files using the ../filename.yml#/objectKey syntax, the bundled swagger creates component keys for the objects using a syntax like filename_objectKey which then introduces an invalid (for aws api gateway) underscore character _. You will see errors in aws such as Unable to create model for 'filename_objectKey': Model name must be alphanumeric: filename_objectKey

Fairly sure this is the offending line https://github.com/Redocly/redocly-cli/blob/eb827254637d3d17a30b2285fad7d37fb5a3318b/packages/core/src/bundle.ts#L392

To Reproduce Steps to reproduce the behavior:

Given a swagger file and a couple of schema files

swagger.yaml

openapi: 3.0.1
paths:
  /v1/foo:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "schemas/foo.yaml#/v1"

  /v1/bar:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "schemas/bar.yaml#/v1"

schemas/foo.yaml

v1:
  type: object
  required:
    - foo
  properties:
    foo:
      type: string

schemas/bar.yaml

v1:
  type: object
  required:
    - bar
  properties:
    bar:
      type: string

Running npx redocly bundle swagger.yaml -o swagger-bundled.yaml yeilds

swagger-bundled.yaml

openapi: 3.0.1
paths:
  /v1/foo:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/v1'
  /v1/bar:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/bar_v1'
components:
  schemas:
    v1:
      type: object
      required:
        - foo
      properties:
        foo:
          type: string
    bar_v1:
      type: object
      required:
        - bar
      properties:
        bar:
          type: string

Note the component at components.schemas.bar_v1

Suggestion: allow customisation/inhibition of the separator character, to avoid fouling aws alphanumeric rule or other downstream validations. Similar to the customisation of the separation character in the split command.

mishabruml avatar Oct 04 '23 15:10 mishabruml

Thanks for reporting! I'm not certain how to name such an option though. @lornajane any suggestions?

tatomyr avatar Oct 13 '23 12:10 tatomyr

Maybe it makes sense to also name it --separator here? It would need different help text though in the context of this command. Something like "Object key separator used when bundling named resources from different files"

lornajane avatar Oct 13 '23 12:10 lornajane

@lornajane I agree, except we might need another separator for something else in the context of bundling. And since bundling is used in the push, stats, preview-docs, join commands (and maybe somewhere else), this option should also be introduced there. Any concerns about that?

tatomyr avatar Oct 13 '23 13:10 tatomyr

I think separator is a good fit, the character that separates array/string joins is referred to as separator by the js Array.join() api which is a similar concept https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join#parameters

mishabruml avatar Oct 13 '23 13:10 mishabruml

I have the exact same problem when uploading the joined OpenAPI spec file to AWS API Gateway.

The possibility to have a custom separator is really appreciated.

I'm OK with naming the parameter as --separator, but something like --prefix-components-separator would be more clear.

jbsilva avatar Oct 17 '23 15:10 jbsilva

Where is it used? Could we use --key-name-separator or does that make it more confusing?

lornajane avatar Oct 19 '23 09:10 lornajane

I would use it with --prefix-components-with-info-prop version.

jbsilva avatar Oct 19 '23 09:10 jbsilva

it may be better to ask AWS to relax this constraint. Adding a customization for an adjacent service could be a slippery slope.

jeremyfiel avatar Oct 19 '23 18:10 jeremyfiel

I agree with @jeremyfiel but still I don't mind adding some generic option. The name for the option is a tricky part though.

I think that the --key-name-separator is not conveying the meaning and I would think it's doing something else. --prefix-components-separator is better.

My suggestion would be --bundle-component-name-separator but it's too lengthy maybe 😅. Any better ideas?

RomanHotsiy avatar Oct 25 '23 07:10 RomanHotsiy

Related (but not actually fixing the problem): a good description of the rules that AWS gateway expects: https://github.com/stoplightio/spectral/issues/475

lornajane avatar Nov 22 '23 09:11 lornajane