graphcommerce-org / graphcommerce

GraphCommerce® is a headless storefront replacement for Magento 2 (PWA), that delivers a faster, better user experience. Fully customizable (React, Next.js) and open-source.
https://www.graphcommerce.org
Other
305 stars 67 forks source link

[RFC] Multi backend optional packages support #1514

Closed paales closed 1 year ago

paales commented 2 years ago

Describe the feature you'd like to request

What will this enable:

What are we running into

Currently we assume a single Magento backend to test all features against; https://backend.reachdigital.dev/graphql

This poses a problem as this backend has both more and less features as other backends at the same time:

When a new GraphCommerce user is following the installation instructions they are required to remove Mollie and Braintree from their setup if they don't have the required Magento backend modules installed.

Or in other words: The user's gernerated GraphQL Mesh schema doesn't have the required Mollie or Braintree GraphQL schema fields available.

So this problem isn't specifically a problem with Magento, but a more general problem that the build GraphQL Mesh schema (the output in the .mesh directory) isn't compatible with the queries that a package might want to call, for example:

This issue also exists the other way around: Our generated GraphQL mesh doesn't provide the fields but PR's want to include queries that assume queries, for example we are working on.


Postcode validation example

The postcode validation service would like to be able to run the following query:

fragment PostcodeFields on query_postcodeServiceNL {
  success
  straatnaam
  woonplaats
}
query Postcode($postcode: ID!, $houseNumber: ID!) {
  postcodeServiceNL(postcode: $postcode, housenumber: $houseNumber) {
      ...PostcodeFields
  }
}

With the current setup in GraphCommerce this results in the following error:

Generate [failed]
→ Fragment "PostcodeFields" is set on non-existing type "query_postcodeServiceNL"!

To make this service work we need to define a new entry in the .meshrc.yml file:

sources:
  - name: postcodeService
    handler:
      jsonSchema:
        baseUrl: https://api.postcodeservice.com
        operations:
          - type: Query
            field: postcodeServiceNL
            path: /nl/v3/json/getAddress/index.php?postcode={args.postcode}&huisnummer={args.housenumber}&client_id={env.POSTCODESERVICE_CLIENT_ID}&secure_code={env.POSTCODESERVICE_SECURE_CODE}
            method: GET
            responseSample: '{"success":true,"straatnaam":"Hertshoornvaren","woonplaats":"Bergschenhoek"}'

This currently however is a manual instruction and isn't automated.

However, not all customers would like to have this functionality and we don't even want to have this functionality in the demo at the moment. This doesn't mean that the feature isn't valuable however, so we we want to have full support these kinds of packages.

Describe the solution you'd like

I think a few features would solve this:

1. Composable mesh configuration files

yarn mesh build should be able to find partial .meshrc.yml files inside each package and merge it with the root .meshrc.yml.

We currently already modify the .meshrc.yml and write it to a temporary .meshrc location and use that one for actual code generation.

2. GraphQL code generation based based on installed packages

Currently we simply do a wildcard match to find all schema files and find all documents.

This should be modified to only scan for schema files and documents that that are installed dependencies in your package.json or indirect dependencies that are used.

Current available groundwork

We do have a somewhat similar feature in the codebase somewhere. Currently packages are all written in typescript and aren't transpiled when published to NPM (because we need to generate the the graphql files etc.), so we transpile them during build time with next-transpile-modules.

However, next-transpile-modules only accepts full module paths. So we already generate a list of packages based on the installed packages.

We can reuse this list to limit the search area of the point 1 and 2.

To enable also including your own packages in this transpilation step and therefor in the future in feature 1 and 2 you would simply need to configure the namespaces that are used with withYarn1Scopes(["@graphcommerce", "@yournamespace"]).

Describe alternatives you've considered

In general I'm against introducing 'magic' that adds functionality automatically when installing packages but it seems a fair tradeoff since we are already non-standard by transpiling typescript and generating gql.ts files.

ErwinOtten commented 2 years ago

Would this solution 'magically' figure out which packages are being used and install them? Or does this require manual configuration of the desired packages in package.json?

mikekeehnen commented 2 years ago

Looking like some solid solutions @paales, does this mean Mollie and Braintree will be treated the same way as the postcodeService package from your example? If it's possible to extract magento extensions (or other platform extensions) in to separate packages, it would make the installation of graphcommerce easier in the sense that it would work for anyone out of the box. It would even be possible to write a configurator for the installation and it would make an amazing section in the docs @ErwinOtten.

hnsr commented 2 years ago

Looks good! Doesn't seem like a lot of magic for the benefits this gives us

GeKVe commented 2 years ago

I LOVE this proposal! Our main project has disabled all MagentoInventory* modules in favor for a more complex ERP system. I think this proposal would simplify the integration in this regard. Would it be an idea (is it even possible?) to split this feature into a separate package, to keep the main package "without magic" ?

paales commented 1 year ago

We'll be following this up with an addtional proposal when the time comes