{"version":3,"file":"parse-metafield.mjs","sources":["../../src/parse-metafield.ts"],"sourcesContent":["import type {\n  Article,\n  Collection,\n  CurrencyCode,\n  GenericFile,\n  Metafield as MetafieldBaseType,\n  MoneyV2,\n  Page,\n  Product,\n  ProductVariant,\n} from './storefront-api-types.js';\nimport type {PartialDeep, Simplify} from 'type-fest';\nimport {flattenConnection} from './flatten-connection.js';\nimport {RootASTNode as RichTextRootASTNode} from './RichText.types.js';\n\n/**\n * A function that uses `metafield.type` to parse the Metafield's `value` or `reference` or `references` (depending on the `metafield.type`) and places the result in `metafield.parsedValue`\n *\n * TypeScript developers can use the type `ParsedMetafields` from this package to get the returned object's type correct. For example:\n *\n * ```\n * parseMetafield<ParsedMetafields['boolean']>({type: 'boolean', value: 'false'}\n * ```\n */\nexport function parseMetafield<ReturnGeneric>(\n  metafield: PartialDeep<MetafieldBaseType, {recurseIntoArrays: true}>,\n): ReturnGeneric {\n  if (!metafield.type) {\n    const noTypeError = `parseMetafield(): The 'type' field is required in order to parse the Metafield.`;\n    if (__HYDROGEN_DEV__) {\n      throw new Error(noTypeError);\n    } else {\n      console.error(`${noTypeError} Returning 'parsedValue' of 'null'`);\n      return {\n        ...metafield,\n        parsedValue: null,\n      } as ReturnGeneric;\n    }\n  }\n\n  switch (metafield.type) {\n    case 'boolean':\n      return {\n        ...metafield,\n        parsedValue: metafield.value === 'true',\n      } as ReturnGeneric;\n\n    case 'article_reference':\n    case 'collection_reference':\n    case 'file_reference':\n    case 'page_reference':\n    case 'product_reference':\n    case 'variant_reference':\n      return {\n        ...metafield,\n        parsedValue: metafield.reference,\n      } as ReturnGeneric;\n\n    case 'color':\n    case 'multi_line_text_field':\n    case 'single_line_text_field':\n    case 'url':\n      return {\n        ...metafield,\n        parsedValue: metafield.value,\n      } as ReturnGeneric;\n\n    // TODO: 'money' should probably be parsed even further to like `useMoney()`, but that logic needs to be extracted first so it's not a hook\n    case 'money': {\n      let parsedValue: MoneyV2 | null = null;\n      try {\n        const parsed = parseJSON(metafield.value ?? '');\n        // Transform currency_code from Storefront API to currencyCode to match MoneyV2 type\n        if (parsed && typeof parsed === 'object' && 'currency_code' in parsed) {\n          const moneyData = parsed as {amount: string; currency_code: string};\n          parsedValue = {\n            amount: moneyData.amount,\n            currencyCode: moneyData.currency_code as CurrencyCode,\n          };\n        } else if (\n          parsed &&\n          typeof parsed === 'object' &&\n          'currencyCode' in parsed\n        ) {\n          // Already in correct format (for backward compatibility)\n          parsedValue = parsed as MoneyV2;\n        } else {\n          parsedValue = parsed as MoneyV2 | null;\n        }\n      } catch (err) {\n        const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n        if (__HYDROGEN_DEV__) {\n          throw new Error(parseError);\n        } else {\n          console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n        }\n        parsedValue = null;\n      }\n      return {\n        ...metafield,\n        parsedValue,\n      } as ReturnGeneric;\n    }\n\n    case 'dimension':\n    case 'json':\n    case 'rating':\n    case 'volume':\n    case 'weight':\n    case 'rich_text_field':\n    case 'list.color':\n    case 'list.dimension':\n    case 'list.number_integer':\n    case 'list.number_decimal':\n    case 'list.rating':\n    case 'list.single_line_text_field':\n    case 'list.url':\n    case 'list.volume':\n    case 'list.weight': {\n      let parsedValue = null;\n      try {\n        parsedValue = parseJSON(metafield.value ?? '');\n      } catch (err) {\n        const parseError = `parseMetafield(): attempted to JSON.parse the 'metafield.value' property, but failed.`;\n        if (__HYDROGEN_DEV__) {\n          throw new Error(parseError);\n        } else {\n          console.error(`${parseError} Returning 'null' for 'parsedValue'`);\n        }\n        parsedValue = null;\n      }\n      return {\n        ...metafield,\n        parsedValue,\n      } as ReturnGeneric;\n    }\n\n    case 'date':\n    case 'date_time':\n      return {\n        ...metafield,\n        parsedValue: new Date(metafield.value ?? ''),\n      } as ReturnGeneric;\n\n    case 'list.date':\n    case 'list.date_time': {\n      const jsonParseValue = parseJSON(metafield?.value ?? '') as string[];\n      return {\n        ...metafield,\n        parsedValue: jsonParseValue.map((dateString) => new Date(dateString)),\n      } as ReturnGeneric;\n    }\n\n    case 'number_decimal':\n    case 'number_integer':\n      return {\n        ...metafield,\n        parsedValue: Number(metafield.value),\n      } as ReturnGeneric;\n\n    case 'list.article_reference':\n    case 'list.collection_reference':\n    case 'list.file_reference':\n    case 'list.page_reference':\n    case 'list.product_reference':\n    case 'list.variant_reference':\n      return {\n        ...metafield,\n        parsedValue: flattenConnection(metafield.references ?? undefined),\n      } as ReturnGeneric;\n\n    default: {\n      const typeNotFoundError = `parseMetafield(): the 'metafield.type' you passed in is not supported. Your type: \"${metafield.type}\". If you believe this is an error, please open an issue on GitHub.`;\n      if (__HYDROGEN_DEV__) {\n        throw new Error(typeNotFoundError);\n      } else {\n        console.error(\n          `${typeNotFoundError}  Returning 'parsedValue' of 'null'`,\n        );\n        return {\n          ...metafield,\n          parsedValue: null,\n        } as ReturnGeneric;\n      }\n    }\n  }\n}\n\n/**\n * Parses a JSON string while preventing prototype injection attacks.\n */\nexport function parseJSON(json: string): unknown {\n  if (String(json).includes('__proto__')) {\n    return JSON.parse(json, (k, v) => {\n      if (k !== '__proto__') return v as unknown;\n    }) as unknown;\n  }\n  return JSON.parse(json) as unknown;\n}\n\n// taken from https://shopify.dev/apps/metafields/types\nexport const allMetafieldTypesArray = [\n  'article_reference',\n  'boolean',\n  'collection_reference',\n  'color',\n  'date',\n  'date_time',\n  'dimension',\n  'file_reference',\n  'json',\n  'money',\n  'rich_text_field',\n  'multi_line_text_field',\n  'number_decimal',\n  'number_integer',\n  'page_reference',\n  'product_reference',\n  'rating',\n  'single_line_text_field',\n  'url',\n  'variant_reference',\n  'volume',\n  'weight',\n  // list metafields\n  'list.article_reference',\n  'list.collection_reference',\n  'list.color',\n  'list.date',\n  'list.date_time',\n  'list.dimension',\n  'list.file_reference',\n  'list.number_integer',\n  'list.number_decimal',\n  'list.page_reference',\n  'list.product_reference',\n  'list.rating',\n  'list.single_line_text_field',\n  'list.url',\n  'list.variant_reference',\n  'list.volume',\n  'list.weight',\n] as const;\n\n/** A union of all the supported `metafield.type`s */\nexport type MetafieldTypeTypes = (typeof allMetafieldTypesArray)[number];\n\n/**\n * A mapping of a Metafield's `type` to the TypeScript type that is returned from `parseMetafield()`\n * For example, when using `parseMetafield()`, the type will be correctly returned when used like the following:\n *\n * ```\n * const parsedMetafield = parseMetafield<ParsedMetafields['boolean']>(metafield);`\n * ```\n * `parsedMetafield.parsedValue`'s type is now `boolean`\n */\nexport type ParsedMetafields<ExtraTypeGeneric = void> = {\n  /** A Metafield that's been parsed, with a `parsedValue` of an `Article` object (as defined by the Storefront API) */\n  article_reference: Simplify<ArticleParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of `boolean` */\n  boolean: Simplify<BooleanParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of a `Collection` object (as defined by the Storefront API) */\n  collection_reference: Simplify<CollectionParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n  color: Simplify<ColorParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n  date: Simplify<DatesParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Date` */\n  date_time: Simplify<DatesParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n  dimension: Simplify<MeasurementParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of a `GenericFile` object (as defined by the Storefront API) */\n  file_reference: Simplify<FileRefParsedMetafield>;\n  /**\n   * A Metafield that's been parsed, with a `parsedValue` of type `unknown`, unless you pass in the type as a generic. For example:\n   *\n   * ```\n   * ParsedMetafields<MyJsonType>['json']\n   * ```\n   */\n  json: Simplify<JsonParsedMetafield<ExtraTypeGeneric>>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Money` */\n  money: Simplify<MoneyParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n  multi_line_text_field: Simplify<TextParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n  number_decimal: Simplify<NumberParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `number` */\n  number_integer: Simplify<NumberParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of a `Page` object (as defined by the Storefront API) */\n  page_reference: Simplify<PageParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of a `Product` object (as defined by the Storefront API) */\n  product_reference: Simplify<ProductParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n  rating: Simplify<RatingParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Rating` */\n  rich_text_field: Simplify<RichTextParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n  single_line_text_field: Simplify<TextParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `string` */\n  url: Simplify<TextParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of a `ProductVariant` object (as defined by the Storefront API) */\n  variant_reference: Simplify<VariantParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n  volume: Simplify<MeasurementParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of type `Measurement` */\n  weight: Simplify<MeasurementParsedMetafield>;\n  // list metafields\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Article` objects (as defined by the Storefront API) */\n  'list.article_reference': Simplify<ArticleListParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Collection` objects (as defined by the Storefront API) */\n  'list.collection_reference': Simplify<CollectionListParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n  'list.color': Simplify<ColorListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n  'list.date': Simplify<DatesListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of Date objects */\n  'list.date_time': Simplify<DatesListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement` objects */\n  'list.dimension': Simplify<MeasurementListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `GenericFile` objects (as defined by the Storefront API) */\n  'list.file_reference': Simplify<FileListParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n  'list.number_integer': Simplify<NumberListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of numbers */\n  'list.number_decimal': Simplify<NumberListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Page` objects (as defined by the Storefront API) */\n  'list.page_reference': Simplify<PageListParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Product` objects (as defined by the Storefront API) */\n  'list.product_reference': Simplify<ProductListParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Rating`s */\n  'list.rating': Simplify<RatingListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n  'list.single_line_text_field': Simplify<TextListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of strings */\n  'list.url': Simplify<TextListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `ProductVariant` objects (as defined by the Storefront API) */\n  'list.variant_reference': Simplify<VariantListParsedRefMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n  'list.volume': Simplify<MeasurementListParsedMetafield>;\n  /** A Metafield that's been parsed, with a `parsedValue` of an array of `Measurement`s */\n  'list.weight': Simplify<MeasurementListParsedMetafield>;\n};\n\ninterface ParsedBase extends MetafieldBaseType {\n  type: MetafieldTypeTypes;\n  parsedValue: unknown;\n}\n\ninterface BooleanParsedMetafield extends ParsedBase {\n  type: 'boolean';\n  parsedValue: boolean | null;\n}\ntype CollectionParsedRefMetafield = MetafieldBaseType & {\n  type: 'collection_reference';\n  parsedValue: Collection | null;\n};\ntype ColorParsedMetafield = MetafieldBaseType & {\n  type: 'color';\n  parsedValue: string | null;\n};\ntype DatesParsedMetafield = MetafieldBaseType & {\n  type: 'date' | 'date_time';\n  parsedValue: Date | null;\n};\n\ntype MeasurementParsedMetafield = MetafieldBaseType & {\n  type: 'dimension' | 'weight' | 'volume';\n  parsedValue: Measurement | null;\n};\n\ntype FileRefParsedMetafield = MetafieldBaseType & {\n  type: 'file_reference';\n  parsedValue: GenericFile | null;\n};\n\ntype JsonParsedMetafield<JsonTypeGeneric = void> = MetafieldBaseType & {\n  type: 'json';\n  parsedValue: JsonTypeGeneric extends void ? unknown : JsonTypeGeneric | null;\n};\n\ntype MoneyParsedMetafield = MetafieldBaseType & {\n  type: 'money';\n  parsedValue: MoneyV2 | null;\n};\n\ntype TextParsedMetafield = MetafieldBaseType & {\n  type: 'single_line_text_field' | 'multi_line_text_field' | 'url';\n  parsedValue: string | null;\n};\n\ntype NumberParsedMetafield = MetafieldBaseType & {\n  type: 'number_decimal' | 'number_integer';\n  parsedValue: number | null;\n};\n\ntype ArticleParsedRefMetafield = MetafieldBaseType & {\n  type: 'article_reference';\n  parsedValue: Article | null;\n};\n\ntype PageParsedRefMetafield = MetafieldBaseType & {\n  type: 'page_reference';\n  parsedValue: Page | null;\n};\n\ntype ProductParsedRefMetafield = MetafieldBaseType & {\n  type: 'product_reference';\n  parsedValue: Product | null;\n};\n\ntype RatingParsedMetafield = MetafieldBaseType & {\n  type: 'rating';\n  parsedValue: Rating | null;\n};\n\ntype RichTextParsedMetafield = MetafieldBaseType & {\n  type: 'rich_text_field';\n  parsedValue: RichTextRootASTNode | null;\n};\n\ntype VariantParsedRefMetafield = MetafieldBaseType & {\n  type: 'variant_reference';\n  parsedValue: ProductVariant | null;\n};\n\ntype ArticleListParsedRefMetafield = MetafieldBaseType & {\n  type: 'list.article_reference';\n  parsedValue: Array<Article> | null;\n};\n\ntype CollectionListParsedRefMetafield = MetafieldBaseType & {\n  type: 'list.collection_reference';\n  parsedValue: Array<Collection> | null;\n};\n\ntype ColorListParsedMetafield = MetafieldBaseType & {\n  type: 'list.color';\n  parsedValue: Array<string> | null;\n};\n\ntype DatesListParsedMetafield = MetafieldBaseType & {\n  type: 'list.date' | 'list.date_time';\n  parsedValue: Array<Date> | null;\n};\n\ntype MeasurementListParsedMetafield = MetafieldBaseType & {\n  type: 'list.dimension' | 'list.weight' | 'list.volume';\n  parsedValue: Array<Measurement> | null;\n};\n\ntype FileListParsedRefMetafield = MetafieldBaseType & {\n  type: 'list.file_reference';\n  parsedValue: Array<GenericFile> | null;\n};\n\ntype TextListParsedMetafield = MetafieldBaseType & {\n  type: 'list.single_line_text_field' | 'list.url';\n  parsedValue: Array<string> | null;\n};\n\ntype NumberListParsedMetafield = MetafieldBaseType & {\n  type: 'list.number_decimal' | 'list.number_integer';\n  parsedValue: Array<number> | null;\n};\n\ntype PageListParsedRefMetafield = MetafieldBaseType & {\n  type: 'list.page_reference';\n  parsedValue: Array<Page> | null;\n};\n\ntype ProductListParsedRefMetafield = MetafieldBaseType & {\n  type: 'list.product_reference';\n  parsedValue: Array<Product> | null;\n};\n\ntype RatingListParsedMetafield = MetafieldBaseType & {\n  type: 'list.rating';\n  parsedValue: Array<Rating> | null;\n};\n\ntype VariantListParsedRefMetafield = MetafieldBaseType & {\n  type: 'list.variant_reference';\n  parsedValue: Array<ProductVariant> | null;\n};\n\nexport type Measurement = {\n  unit: string;\n  value: number;\n};\n\nexport interface Rating {\n  value: number;\n  scale_min: number;\n  scale_max: number;\n}\n"],"names":[],"mappings":"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"}