frontends icon indicating copy to clipboard operation
frontends copied to clipboard

[BUG] @shopware/api-gen not behaving as expected when applying multiple patches.

Open max-zinn opened this issue 10 months ago • 6 comments

Current Behavior

The @shopware/api-gen package doesn't work when two patches affect the same schema.

Expected Behavior

I found the patch linked by the npm package here: https://raw.githubusercontent.com/shopware/frontends/main/packages/api-client/api-types/storeApiSchema.overrides.json

But I also want to customize the customFields property to our needs. You can see a minimal example in this repository (storeApiTypes.overrides.json). Since both apply changes to the Product schema, only the first one (in this case the shopware default patch) is applied.

Simply checkout this repository and run

pnpm api:generate

The result is the applied patch including the one for calculatedCheapestPrice, but not the patch for customFields. Swap the order of both patches in api-gen.config.json and the result will change. Now the patch for customFields is applied but not the patch for calculatedCheapestPrice.


I really don't understand the underlying mechanic as I expected it to apply patches by simply deepmerging all patches after each other into the storeApiSchema.json and then generating the storeApiTypes.d.ts based on the openAPI specs.

The documentation of @shopware/api-gen states the following:

Partial overrides are applied directly to the JSON schema, so the syntax needs to be correct

Why do I have to use a different schema than the storeApiSchema.json? The structure there is:

{
  "components": {
    "schemas": {
      "Product": {}
    }
  }
}

whereas the storeApiTypes.overrides.json requires the following structure:

{
  "components": {
    "Products": {}
  }
}

If I use the same structure as originally defined, it doesn't work at all.

Steps To Reproduce

  1. Checkout my reproduction repository: https://github.com/max-zinn/api-gen-patch-bug
  2. read the README.md, it should give enough explanation on the issue.

Anything else?

No response

max-zinn avatar Feb 26 '25 14:02 max-zinn

hey @max-zinn looking at the overrides we currently can override:

  1. components
  2. patches

Here's more info on that: https://github.com/shopware/frontends/tree/main/packages/api-gen#partial-overrides

What is the problem in your case:

  1. you named component CustomFields instead of CustomField when you extended it (but still can be like this if you want)
  2. the problem was Product overriding - it already has patches, so you should add yours in array

Working override for you would be (although I would suggest to change CustomFIelds to CustomField):

{
  "components": {
    "Product": [
      {
        "properties": {
          "customFields": {
            "$ref": "#/components/schemas/CustomFields"
          }
        }
      }
    ],
    "CustomFields": {
      "properties": {
        "my_custom_field": {
          "type": "string",
          "required": true
        }
      }
    }
  }
}

so result is:

Image

Image

patzick avatar Mar 07 '25 10:03 patzick

Hey @patzick, thanks for the clarification. I understood the documentation as "you can choose array or object syntax to your preferences".

The documentation didn't state that every patch file needs to have the same format of applying patches.

you apply this as 2 independent patches, or combine it as a single patch without array:

I just tested this out and both patch files get only applied if they follow the same structure.


Example:

given this api-gen.config.json

{
    "$schema": "https://raw.githubusercontent.com/shopware/frontends/main/packages/api-gen/api-gen.schema.json",
    "patches": ["api-types/storeApiTypes2.overrides.json", "api-types/storeApiTypes3.overrides.json"]
}

Following are four variants where there are issues I got confused with:

// api-types/storeApiTypes2.overrides.json
{
    "components": {
        "Product": {
            "required": ["weight"]
        }
    }
}

// api-types/storeApiTypes3.overrides.json
{
    "components": {
        "Product": {
            "required": ["versionId"]
        }
    }
}

This works because both files use object syntax for patching the product


// api-types/storeApiTypes2.overrides.json
{
    "components": {
        "Product": [
            {
                "required": ["weight"]
            }
        ]
    }
}

// api-types/storeApiTypes3.overrides.json
{
    "components": {
        "Product": [
            {
                "required": ["versionId"]
            }
        ]
    }
}

This also works because both files use array syntax


// api-types/storeApiTypes2.overrides.json
{
    "components": {
        "Product": {
            "required": ["weight"]
        }
    }
}

// api-types/storeApiTypes3.overrides.json
{
    "components": {
        "Product": [
            {
                "required": ["versionId"]
            }
        ]
    }
}

This doesn't work, only the first patch is applied


// api-types/storeApiTypes2.overrides.json
{
    "components": {
        "Product": [
            {
                "required": ["weight"]
            }
        ]
    }
}

// api-types/storeApiTypes3.overrides.json
{
    "components": {
        "Product": {
            "required": ["versionId"]
        }
    }
}

This doesn't work, only the first patch is applied


If this is intended behaviour, I'd highly suggest updating the README to clearly state this.

I can create a PR with a suggestion for the README.md if you like.

max-zinn avatar Mar 07 '25 10:03 max-zinn

Regarding

you named component CustomFields instead of CustomField when you extended it (but still can be like this if you want)

I didn't want to extendd the existing CustomField because it's not used anywhere in the storeApiSchema.json but since it's a type in the generated output, I have no idea where this type might be used and my change could break something else.

It had no reference to the Product schema as well so I figured I create CustomFields as a new type and $ref it to the Product schema.

max-zinn avatar Mar 07 '25 10:03 max-zinn

that's also fine, it just looked like a typo ;)

So it that working for you in current shape?

patzick avatar Mar 07 '25 11:03 patzick

sorry missed you typed two comments :)

yes, you're right about not clear info. You're use case is totally valid. I think we can solve this on merging patches - so if there already is patch for specific route we can enforce array under the hood. That's why I'm not closing that one yet as well 🙌

patzick avatar Mar 07 '25 11:03 patzick

Sounds good, thanks! In any way, I already made some changes to the README.md and posted a PR. It's up to you if you want to accept it and/or make the changes :)

Happy weekend!

max-zinn avatar Mar 07 '25 11:03 max-zinn