Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse Metaobjects Utility #1621

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Parse Metaobjects Utility #1621

wants to merge 1 commit into from

Conversation

celsowhite
Copy link
Contributor

Overview

Create a utility function that helps users parse metaobject fields. Speed up development processes by helping users move more quickly from metaobject graphql queries to being able to consume the data in their app.

Current Approaches

Right now its common for teams/project to create their own utilities to parse the metaobject query response. Mainly so they can attach field keys directly to their parsedValues. It would be nice to standardize and provide it out the box.

Benefits

  • Recursive References - Formatting metaobject fields gets a bit tricky especially when dealing with deeply nested metaobject references. This function will handle formatting deeply nested fields.
  • Key/Value Formatting - A typical way to access field data in an app is through properties. Raw fields data is formatted as an array. This formatter would convert fields to an object so properties can more easily be accessed.

Usage

There are two primary ways that this function will be used:

  • Metaobject Query - A user has queried a specific metaobject via the api by specifying the handle or id. Once the data is returned they’d like to pass it through the parseMetaobject helper to get the properly formatted fields.
  • Metafield Query - A user would like to format metaobjects that have been referenced via metafields. The assignment can happen directly to a top level metafield or could be included within the field set of another metaobject.

Example Dev Experience

Graph QL Query

The original graphql query for a specific metaobject. This example includes a nested metaobject reference to show how that might be parsed. It'll be common to have nested metaobjects 2-3 levels deep.

query pageBuilder($handle: String!) {
  metaobject(handle: {type: "page_builder", handle: $handle}) {
    type
    fields {
      key
      type
      value
      reference {
        __typename
        ...on Metaobject {
          type
          fields {
            type
            key
            value
          }
        }
      }
    }
  }
}

Query Result

The unformatted output from the graphql api.

{
  "data": {
    "metaobject": {
      "type": "page_builder",
      "fields": [
        {
          "type": "single_line_text_field",
          "key": "name",
          "value": "Homepage",
          "reference": null
        },
        {
          "type": "metaobject_reference",
          "key": "hero",
          "value": "gid://shopify/Metaobject/id",
          "reference": {
            "type": "hero",
            "fields": [
              {
                "type": "single_line_text_field",
                "key": "title",
                "value": "Shop New Products"
              },
              {
                "type": "file_reference",
                "key": "image",
                "value": "gid://shopify/MediaImage/id",
                "reference": {
                  "image": {
                    "id": "gid://shopify/ImageSource/id",
                    "url": "https://cdn.shopify.com/s/files/id"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Trigger Function

The user would trigger the utility by passing the metaobject to the function.

parseMetaobject(queryResult.data.metaobject);

Output Option 1

Formatted output transforming fields into parsedFields. The fields within parsedFields will have the exact output of the parseMetafield utility.

{
  "type": "page_builder",
  "fields": <Original Fields Array>,
  "parsedFields": {
    "name": {
      "type": "single_line_text_field",
      "key": "name",
      "value": "Homepage",
      "parsedValue": "Homepage",
      "reference": null
    },
    "hero": {
      "type": "metaobject_reference",
      "key": "hero",
      "value": "gid://shopify/Metaobject/id",
      "reference": <Original Reference Object>,
      "parsedValue": {
        "type": "hero",
        "fields": <Original Fields Array>,
        "parsedFields": {
          "title": {
            "type": "single_line_text_field",
            "value": "Shop New Products",
            "parsedValue": "Shop New Products",
            "reference": null
          },
          "image": {
            "type": "file_reference",
            "value": "gid://shopify/MediaImage/id",
            "parsedValue": {
              "image": {
                "id": "gid://shopify/ImageSource/id",
                "url": "https://cdn.shopify.com/s/files/id"
              }
            },
            "reference": <Original Image Reference Object>
          }
        }
      },
    }
  }
}

Output Option 2

Transform the output to directly attach parsed values to the field keys. This streamlines and makes the data easier to access but does create a discrepency in the data structures between fields within metaobjects and normal fields that were parsed directly with the parseMetafield utility.

{
  "type": "page_builder",
  "fields": <Original Fields Array>,
  "parsedFields": {
    "name": "Homepage",
    "hero": {
      "fields": <Original Fields Array>,
      "parsedFields": {
        "title": "Shop New Products",
        "image": {
          "image": {
            "id": "gid://shopify/ImageSource/id",
            "url": "https://cdn.shopify.com/s/files/id"
          }
        }
      }
    }
  }
}

Implementation

To implement this we need to do a few things. This draft pr attempts to get the bones in place for these changes. Feedback on approach is more than welcome!

  1. Include single metaobject reference types in the parseMetafield helper.
  2. Include list type metaobject references in the parseMetafield helper.
  3. Create a specific parseMetaobject helper. This would essentially decorate a metaobject with additional metafield properties and call parseMetafield helper with it.

Open Questions

  • Are we ok with converting the parsedFields key to object syntax instead of an array? The downsides of an array is that even after parsing, the field values can't be referenced directly through chaining. This becomes even more complex when accessing deeply nested data.
  • How much transformation is too much transformation of the parsedFields? One thing I like about Option 2 is it'll reduce the amount of chaining. Ex. metaobject.parsedFields.hero.parsedValue.parsedFields.title.parsedValue becomes metaobject.parsedFields.hero.parsedFields.title.
  • Is there a world where a user can specify the field output (1 or 2) via param parseMetaobject(metaobject: value, streamlined: true)?

Copy link
Contributor

github-actions bot commented Jan 8, 2024

We detected some changes in packages/*/package.json or packages/*/src, and there are no updates in the .changeset.
If the changes are user-facing and should cause a version bump, run npm run changeset add to track your changes and include them in the next release CHANGELOG.
If you are making simple updates to examples or documentation, you do not need to add a changeset.

@celsowhite celsowhite marked this pull request as draft January 8, 2024 19:06
@juanpprieto juanpprieto self-assigned this Jan 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants