fix: fixes to extract the metafields for products

This commit is contained in:
talatops 2026-04-11 23:09:18 +05:00
parent a86c805cda
commit 7958b32159

View File

@ -8,15 +8,25 @@ export type CachedShopifyMetafield = {
type: string type: string
} }
type GraphQLMetaobjectRef = {
displayName?: string | null
} | null
type GraphQLMetafieldNode = {
namespace?: string
key?: string
value?: string | null
type?: string
reference?: GraphQLMetaobjectRef
references?: {
nodes?: GraphQLMetaobjectRef[]
} | null
}
type GraphQLProductNode = { type GraphQLProductNode = {
legacyResourceId?: string | number | null legacyResourceId?: string | number | null
metafields?: { metafields?: {
nodes?: Array<{ nodes?: Array<GraphQLMetafieldNode | null> | null
namespace?: string
key?: string
value?: string | null
type?: string
} | null> | null
} | null } | null
} | null } | null
@ -28,6 +38,39 @@ type GraphQLResponse = {
const GRAPHQL_API_VERSION = "2024-10" const GRAPHQL_API_VERSION = "2024-10"
/** Keep batches small to stay under GraphQL cost limits (many metafields per product). */ /** Keep batches small to stay under GraphQL cost limits (many metafields per product). */
const PRODUCT_IDS_PER_REQUEST = 35 const PRODUCT_IDS_PER_REQUEST = 35
/** Max entries per list.metaobject_reference (taxonomy lists are usually small). */
const METAFIELD_REFERENCES_FIRST = 50
function displayNameFromRef(ref: GraphQLMetaobjectRef): string | undefined {
if (!ref || typeof ref !== "object") return undefined
const d = ref.displayName
if (typeof d !== "string") return undefined
const t = d.trim()
return t.length > 0 ? t : undefined
}
/**
* Shopify stores metaobject metafields as GID(s) in `value`. Replace with human-readable
* labels from GraphQL `reference` / `references` when present.
*/
function resolvedMetafieldValue(n: GraphQLMetafieldNode, raw: string | null, type: string): string | null {
if (raw === null) return null
if (type === "metaobject_reference") {
const label = displayNameFromRef(n.reference ?? null)
return label ?? raw
}
if (type === "list.metaobject_reference") {
const refNodes = n.references?.nodes
if (!Array.isArray(refNodes) || refNodes.length === 0) return raw
const labels = refNodes.map((r) => displayNameFromRef(r)).filter((x): x is string => Boolean(x))
if (labels.length === 0) return raw
return JSON.stringify(labels)
}
return raw
}
function toRows(metafields: NonNullable<GraphQLProductNode>["metafields"]): CachedShopifyMetafield[] { function toRows(metafields: NonNullable<GraphQLProductNode>["metafields"]): CachedShopifyMetafield[] {
const nodes = metafields?.nodes const nodes = metafields?.nodes
@ -35,11 +78,13 @@ function toRows(metafields: NonNullable<GraphQLProductNode>["metafields"]): Cach
const out: CachedShopifyMetafield[] = [] const out: CachedShopifyMetafield[] = []
for (const n of nodes) { for (const n of nodes) {
if (!n || typeof n.namespace !== "string" || typeof n.key !== "string") continue if (!n || typeof n.namespace !== "string" || typeof n.key !== "string") continue
const type = typeof n.type === "string" ? n.type : "unknown"
const raw = n.value ?? null
out.push({ out.push({
namespace: n.namespace, namespace: n.namespace,
key: n.key, key: n.key,
value: n.value ?? null, value: resolvedMetafieldValue(n, raw, type),
type: typeof n.type === "string" ? n.type : "unknown", type,
}) })
} }
return out return out
@ -76,6 +121,18 @@ export async function fetchProductMetafieldsMap(
key key
value value
type type
reference {
... on Metaobject {
displayName
}
}
references(first: ${METAFIELD_REFERENCES_FIRST}) {
nodes {
... on Metaobject {
displayName
}
}
}
} }
} }
} }