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

Auto-complete metafields depending on shop data #534

Merged
merged 1 commit into from
Nov 7, 2024

Conversation

aswamy
Copy link
Contributor

@aswamy aswamy commented Oct 18, 2024

What are you adding in this PR?

Part 1 for #502

  • Adding support for metadata autocompletion on our editors
  • listens to file changes for .shopify folder
  • This should work for VScode only

What's next? Any followup issues?

  • We need to make it work on OSE next
  • We will create a CLI command to fetch the metafields.json
  • We need to automatically call this CLI command in VSCode on startup

What did you learn?

  • registering for DidChangeWatchedFilesNotification took some time, but had to read-up on client capabilities and how to subscribe to notifications after initialization

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles

Tophat

Run the following query and dump the contents into .shopify/metafields.json in the theme repository. Remove the nodes array, and place it directory under each group.

query {
	article: metafieldDefinitions(ownerType: ARTICLE, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	blog: metafieldDefinitions(ownerType: BLOG, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	brand: metafieldDefinitions(ownerType: BRAND, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	collection: metafieldDefinitions(ownerType: COLLECTION, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	company: metafieldDefinitions(ownerType: COMPANY, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	company_location: metafieldDefinitions(ownerType: COMPANY_LOCATION, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	location: metafieldDefinitions(ownerType: LOCATION, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	market: metafieldDefinitions(ownerType: MARKET, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	order: metafieldDefinitions(ownerType: ORDER, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	page: metafieldDefinitions(ownerType: PAGE, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	product: metafieldDefinitions(ownerType: PRODUCT, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	variant: metafieldDefinitions(ownerType: PRODUCTVARIANT, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
	shop: metafieldDefinitions(ownerType: SHOP, first: 250) {
		nodes {
			...MetafieldDefinitionFields
		}
	}
}

fragment MetafieldDefinitionFields on MetafieldDefinition {
	name
	namespace
	description
	type {
		category
		name
	}
}

Before you deploy

  • I included a minor bump changeset
  • My feature is backward compatible

@aswamy aswamy force-pushed the auto-complete-metafields branch 5 times, most recently from 0794386 to c17af0c Compare October 25, 2024 21:31
@aswamy aswamy force-pushed the auto-complete-metafields branch 7 times, most recently from b740a20 to ec1edd6 Compare October 30, 2024 22:49
@aswamy aswamy marked this pull request as ready for review October 30, 2024 22:51
@aswamy
Copy link
Contributor Author

aswamy commented Nov 1, 2024

  • changed memo to memoize and used the rootUri as memo key
  • updated file paths so it is OS agnostic
  • updated metafield namespace types to have the format product_metafield_${namespace}
  • changed the format of metafields.json (see changeset)
  • changed memoize function as we discussed + added a test case file since it was missing 😁

@aswamy aswamy changed the title [Draft] Auto-complete metafields depending on shop data Auto-complete metafields depending on shop data Nov 1, 2024
@aswamy
Copy link
Contributor Author

aswamy commented Nov 5, 2024

  • updated to remove unused getMetafieldDefinitions in unit tests
  • updated usage of findThemeRootURI(...) within onDidChangeWatchedFiles
  • changed getMetafieldDefinitions inside theme-check so it can be injected


if (!metafieldsProperty) continue;

metafieldsProperty.return_type = [{ type: `${category}_metafields`, name: '' }];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Thinking about this, are we sure we're not mutating the original object here? Should we clone/replace metafieldsProperty before doing this mutation?

Remember that ...objectMap gives you a shallow clone of the object map. Looks like we're mutating the original object map here and this is no bueno. Means that if you'd get metafield data from one theme in another.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we're mutating the original object map here and this is no bueno. Means that if you'd get metafield data from one theme in another.

OH i didn't know that! Yeah this is actually modifying existing type's properties. E.g. product would be modified so that it's metafields property would return product_metafields instead of untyped.

I guess i could clone product, modify its property, and add it to result 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about it in person - since this isn't unique to a theme, we should be fine with this change happening across themes within a workspace. Added a warning message in a comment above the block instead.

...new Set([...Object.values(METAFIELD_TYPE_TO_TYPE), ...FETCHED_METAFIELD_CATEGORIES]),
].reduce((map, type) => {
{
const metafieldEntry = JSON.parse(JSON.stringify(baseMetafieldEntry)); // easy deep clone
Copy link
Contributor

@charlespwd charlespwd Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh are we doing it already. I'll just dm you to verify :D this code is dense and hard to review lol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sorry there are three things happening to make the whole thing work. We can talk about it more today, but here are the things:

  • customMetafieldTypeEntries --> we copy the metafield type and create one for each category we support. e.g. product_metafield, collection_metafield, etc.
  • metafieldDefinitionsObjectMap --> reads the metafield definitions we fetched and converts it into types for auto-completion
  • the for-loop you commented above --> we override existing types like product and collection, so their metafields properties don't return as untyped, but instead return product_metafields and collection_metafields respectively

Copy link
Contributor

@charlespwd charlespwd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, didn't tophat yet 👀

@aswamy aswamy force-pushed the auto-complete-metafields branch 2 times, most recently from 1b68cbc to 44eff4c Compare November 6, 2024 16:15
@aswamy aswamy merged commit 6014dfd into main Nov 7, 2024
6 checks passed
@aswamy aswamy deleted the auto-complete-metafields branch November 7, 2024 18:50
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.

2 participants