@anker-in/lib 0.0.0-beta.1 → 0.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitkeep +0 -0
- package/.turbo/turbo-build.log +22 -0
- package/.turbo/turbo-test.log +5 -0
- package/dist/cjs/context/HeadlessProvider.js +1 -1
- package/dist/cjs/context/HeadlessProvider.js.map +2 -2
- package/dist/context/HeadlessProvider.d.ts.map +1 -1
- package/dist/esm/cart/const.js +2 -0
- package/dist/esm/cart/const.js.map +7 -0
- package/dist/esm/cart/hooks/basic/useBuyNow.js +2 -0
- package/dist/esm/cart/hooks/basic/useBuyNow.js.map +7 -0
- package/dist/esm/cart/index.js +2 -0
- package/dist/esm/cart/index.js.map +7 -0
- package/dist/esm/cart/track/fbq.js +2 -0
- package/dist/esm/cart/track/fbq.js.map +7 -0
- package/dist/esm/cart/types/index.js +1 -0
- package/dist/esm/cart/types/index.js.map +7 -0
- package/dist/esm/cart/utils/index.js +2 -0
- package/dist/esm/cart/utils/index.js.map +7 -0
- package/dist/esm/context/HeadlessProvider.js +2 -0
- package/dist/esm/context/HeadlessProvider.js.map +7 -0
- package/dist/esm/context/config.js +1 -0
- package/dist/esm/context/config.js.map +7 -0
- package/dist/esm/context/index.js +2 -0
- package/dist/esm/context/index.js.map +7 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/shopify/fetchers/add-cart-lines.js +2 -0
- package/dist/esm/shopify/fetchers/add-cart-lines.js.map +7 -0
- package/dist/esm/shopify/fetchers/create-cart.js +2 -0
- package/dist/esm/shopify/fetchers/create-cart.js.map +7 -0
- package/dist/esm/shopify/fetchers/get-cart.js +2 -0
- package/dist/esm/shopify/fetchers/get-cart.js.map +7 -0
- package/dist/esm/shopify/fetchers/get-products-by-handles.js +2 -0
- package/dist/esm/shopify/fetchers/get-products-by-handles.js.map +7 -0
- package/dist/esm/shopify/fetchers/index.js +2 -0
- package/dist/esm/shopify/fetchers/index.js.map +7 -0
- package/dist/esm/shopify/fetchers/remove-cart-lines.js +2 -0
- package/dist/esm/shopify/fetchers/remove-cart-lines.js.map +7 -0
- package/dist/esm/shopify/fetchers/update-cart-attributes.js +2 -0
- package/dist/esm/shopify/fetchers/update-cart-attributes.js.map +7 -0
- package/dist/esm/shopify/fetchers/update-cart-buyer-identity.js +2 -0
- package/dist/esm/shopify/fetchers/update-cart-buyer-identity.js.map +7 -0
- package/dist/esm/shopify/fetchers/update-cart-codes.js +2 -0
- package/dist/esm/shopify/fetchers/update-cart-codes.js.map +7 -0
- package/dist/esm/shopify/fetchers/update-cart-lines.js +2 -0
- package/dist/esm/shopify/fetchers/update-cart-lines.js.map +7 -0
- package/dist/esm/shopify/fragments/article.js +50 -0
- package/dist/esm/shopify/fragments/article.js.map +7 -0
- package/dist/esm/shopify/fragments/blog.js +11 -0
- package/dist/esm/shopify/fragments/blog.js.map +7 -0
- package/dist/esm/shopify/fragments/cart.js +189 -0
- package/dist/esm/shopify/fragments/cart.js.map +7 -0
- package/dist/esm/shopify/fragments/collection.js +16 -0
- package/dist/esm/shopify/fragments/collection.js.map +7 -0
- package/dist/esm/shopify/fragments/image.js +9 -0
- package/dist/esm/shopify/fragments/image.js.map +7 -0
- package/dist/esm/shopify/fragments/index.js +2 -0
- package/dist/esm/shopify/fragments/index.js.map +7 -0
- package/dist/esm/shopify/fragments/metafields.js +16 -0
- package/dist/esm/shopify/fragments/metafields.js.map +7 -0
- package/dist/esm/shopify/fragments/page-info.js +9 -0
- package/dist/esm/shopify/fragments/page-info.js.map +7 -0
- package/dist/esm/shopify/fragments/page.js +13 -0
- package/dist/esm/shopify/fragments/page.js.map +7 -0
- package/dist/esm/shopify/fragments/product.js +72 -0
- package/dist/esm/shopify/fragments/product.js.map +7 -0
- package/dist/esm/shopify/fragments/seo.js +7 -0
- package/dist/esm/shopify/fragments/seo.js.map +7 -0
- package/dist/esm/shopify/fragments/variant.js +30 -0
- package/dist/esm/shopify/fragments/variant.js.map +7 -0
- package/dist/esm/shopify/gql/fragment-masking.js +2 -0
- package/dist/esm/shopify/gql/fragment-masking.js.map +7 -0
- package/dist/esm/shopify/gql/gql.js +2 -0
- package/dist/esm/shopify/gql/gql.js.map +7 -0
- package/dist/esm/shopify/gql/graphql.js +2 -0
- package/dist/esm/shopify/gql/graphql.js.map +7 -0
- package/dist/esm/shopify/gql/index.js +2 -0
- package/dist/esm/shopify/gql/index.js.map +7 -0
- package/dist/esm/shopify/hooks/index.js +2 -0
- package/dist/esm/shopify/hooks/index.js.map +7 -0
- package/dist/esm/shopify/hooks/useProductsByHandles.js +2 -0
- package/dist/esm/shopify/hooks/useProductsByHandles.js.map +7 -0
- package/dist/esm/shopify/index.js +2 -0
- package/dist/esm/shopify/index.js.map +7 -0
- package/dist/esm/shopify/mutations/add-cart-lines.js +15 -0
- package/dist/esm/shopify/mutations/add-cart-lines.js.map +7 -0
- package/dist/esm/shopify/mutations/create-cart.js +21 -0
- package/dist/esm/shopify/mutations/create-cart.js.map +7 -0
- package/dist/esm/shopify/mutations/remove-cart-items.js +15 -0
- package/dist/esm/shopify/mutations/remove-cart-items.js.map +7 -0
- package/dist/esm/shopify/mutations/update-cart-attributes.js +15 -0
- package/dist/esm/shopify/mutations/update-cart-attributes.js.map +7 -0
- package/dist/esm/shopify/mutations/update-cart-buyer-identity.js +15 -0
- package/dist/esm/shopify/mutations/update-cart-buyer-identity.js.map +7 -0
- package/dist/esm/shopify/mutations/update-cart-discount-code.js +15 -0
- package/dist/esm/shopify/mutations/update-cart-discount-code.js.map +7 -0
- package/dist/esm/shopify/mutations/update-cart-items.js +15 -0
- package/dist/esm/shopify/mutations/update-cart-items.js.map +7 -0
- package/dist/esm/shopify/queries/get-cart.js +13 -0
- package/dist/esm/shopify/queries/get-cart.js.map +7 -0
- package/dist/esm/shopify/queries/get-product-by-handles.js +29 -0
- package/dist/esm/shopify/queries/get-product-by-handles.js.map +7 -0
- package/dist/esm/shopify/queries/index.js +2 -0
- package/dist/esm/shopify/queries/index.js.map +7 -0
- package/dist/esm/shopify/types/article.js +1 -0
- package/dist/esm/shopify/types/article.js.map +7 -0
- package/dist/esm/shopify/types/cart.js +1 -0
- package/dist/esm/shopify/types/cart.js.map +7 -0
- package/dist/esm/shopify/types/checkout.js +1 -0
- package/dist/esm/shopify/types/checkout.js.map +7 -0
- package/dist/esm/shopify/types/collection.js +1 -0
- package/dist/esm/shopify/types/collection.js.map +7 -0
- package/dist/esm/shopify/types/common.js +1 -0
- package/dist/esm/shopify/types/common.js.map +7 -0
- package/dist/esm/shopify/types/config.js +1 -0
- package/dist/esm/shopify/types/config.js.map +7 -0
- package/dist/esm/shopify/types/customer.js +1 -0
- package/dist/esm/shopify/types/customer.js.map +7 -0
- package/dist/esm/shopify/types/fetcher.js +2 -0
- package/dist/esm/shopify/types/fetcher.js.map +7 -0
- package/dist/esm/shopify/types/index.js +2 -0
- package/dist/esm/shopify/types/index.js.map +7 -0
- package/dist/esm/shopify/types/page.js +1 -0
- package/dist/esm/shopify/types/page.js.map +7 -0
- package/dist/esm/shopify/types/product.js +1 -0
- package/dist/esm/shopify/types/product.js.map +7 -0
- package/dist/esm/shopify/types/search.js +1 -0
- package/dist/esm/shopify/types/search.js.map +7 -0
- package/dist/esm/shopify/types/site.js +1 -0
- package/dist/esm/shopify/types/site.js.map +7 -0
- package/dist/esm/shopify/types/type-helper.js +1 -0
- package/dist/esm/shopify/types/type-helper.js.map +7 -0
- package/dist/esm/shopify/utils/colors.js +2 -0
- package/dist/esm/shopify/utils/colors.js.map +7 -0
- package/dist/esm/shopify/utils/const.js +2 -0
- package/dist/esm/shopify/utils/const.js.map +7 -0
- package/dist/esm/shopify/utils/cookie.js +2 -0
- package/dist/esm/shopify/utils/cookie.js.map +7 -0
- package/dist/esm/shopify/utils/errors.js +3 -0
- package/dist/esm/shopify/utils/errors.js.map +7 -0
- package/dist/esm/shopify/utils/fetch-graphql-api.js +3 -0
- package/dist/esm/shopify/utils/fetch-graphql-api.js.map +7 -0
- package/dist/esm/shopify/utils/handle-fetch-response.js +2 -0
- package/dist/esm/shopify/utils/handle-fetch-response.js.map +7 -0
- package/dist/esm/shopify/utils/helper.js +2 -0
- package/dist/esm/shopify/utils/helper.js.map +7 -0
- package/dist/esm/shopify/utils/normalize/cart.js +2 -0
- package/dist/esm/shopify/utils/normalize/cart.js.map +7 -0
- package/dist/esm/shopify/utils/normalize/customer.js +2 -0
- package/dist/esm/shopify/utils/normalize/customer.js.map +7 -0
- package/dist/esm/shopify/utils/normalize/index.js +2 -0
- package/dist/esm/shopify/utils/normalize/index.js.map +7 -0
- package/dist/esm/shopify/utils/normalize/metafield.js +2 -0
- package/dist/esm/shopify/utils/normalize/metafield.js.map +7 -0
- package/dist/esm/shopify/utils/normalize/product.js +2 -0
- package/dist/esm/shopify/utils/normalize/product.js.map +7 -0
- package/dist/esm/shopify/utils/store.js +2 -0
- package/dist/esm/shopify/utils/store.js.map +7 -0
- package/dist/esm/shopify/utils/type-helper.js +1 -0
- package/dist/esm/shopify/utils/type-helper.js.map +7 -0
- package/esbuild-cjs.mjs +23 -0
- package/esbuild-esm.mjs +30 -0
- package/jest.config.ts +12 -0
- package/package.json +10 -13
- package/src/cart/const.ts +23 -0
- package/src/cart/hooks/basic/useBuyNow.ts +105 -0
- package/src/cart/index.ts +19 -0
- package/src/cart/track/fbq.ts +63 -0
- package/src/cart/types/index.ts +25 -0
- package/src/cart/utils/index.ts +22 -0
- package/src/context/HeadlessProvider.tsx +30 -0
- package/src/context/config.ts +10 -0
- package/src/context/index.ts +3 -0
- package/src/index.ts +22 -0
- package/src/shopify/fetchers/add-cart-lines.ts +53 -0
- package/src/shopify/fetchers/create-cart.ts +43 -0
- package/src/shopify/fetchers/get-cart.ts +48 -0
- package/src/shopify/fetchers/get-products-by-handles.ts +48 -0
- package/src/shopify/fetchers/index.ts +10 -0
- package/src/shopify/fetchers/remove-cart-lines.ts +31 -0
- package/src/shopify/fetchers/update-cart-attributes.ts +29 -0
- package/src/shopify/fetchers/update-cart-buyer-identity.ts +32 -0
- package/src/shopify/fetchers/update-cart-codes.ts +32 -0
- package/src/shopify/fetchers/update-cart-lines.ts +42 -0
- package/src/shopify/fragments/article.ts +51 -0
- package/src/shopify/fragments/blog.ts +10 -0
- package/src/shopify/fragments/cart.ts +193 -0
- package/src/shopify/fragments/collection.ts +15 -0
- package/src/shopify/fragments/image.ts +8 -0
- package/src/shopify/fragments/index.ts +11 -0
- package/src/shopify/fragments/metafields.ts +17 -0
- package/src/shopify/fragments/page-info.ts +8 -0
- package/src/shopify/fragments/page.ts +12 -0
- package/src/shopify/fragments/product.ts +71 -0
- package/src/shopify/fragments/seo.ts +6 -0
- package/src/shopify/fragments/variant.ts +29 -0
- package/src/shopify/gql/fragment-masking.ts +85 -0
- package/src/shopify/gql/gql.ts +110 -0
- package/src/shopify/gql/graphql.ts +11780 -0
- package/src/shopify/gql/index.ts +4 -0
- package/src/shopify/hooks/index.ts +1 -0
- package/src/shopify/hooks/useProductsByHandles.ts +24 -0
- package/src/shopify/index.ts +5 -0
- package/src/shopify/mutations/add-cart-lines.ts +16 -0
- package/src/shopify/mutations/create-cart.ts +22 -0
- package/src/shopify/mutations/remove-cart-items.ts +16 -0
- package/src/shopify/mutations/update-cart-attributes.ts +16 -0
- package/src/shopify/mutations/update-cart-buyer-identity.ts +16 -0
- package/src/shopify/mutations/update-cart-discount-code.ts +16 -0
- package/src/shopify/mutations/update-cart-items.ts +16 -0
- package/src/shopify/queries/get-cart.ts +14 -0
- package/src/shopify/queries/get-product-by-handles.ts +32 -0
- package/src/shopify/queries/index.ts +2 -0
- package/src/shopify/types/article.ts +46 -0
- package/src/shopify/types/cart.ts +204 -0
- package/src/shopify/types/checkout.ts +44 -0
- package/src/shopify/types/collection.ts +104 -0
- package/src/shopify/types/common.ts +53 -0
- package/src/shopify/types/config.ts +14 -0
- package/src/shopify/types/customer.ts +31 -0
- package/src/shopify/types/fetcher.ts +67 -0
- package/src/shopify/types/index.ts +11 -0
- package/src/shopify/types/page.ts +45 -0
- package/src/shopify/types/product.ts +176 -0
- package/src/shopify/types/search.ts +62 -0
- package/src/shopify/types/site.ts +38 -0
- package/src/shopify/types/type-helper.ts +5 -0
- package/src/shopify/utils/colors.ts +206 -0
- package/src/shopify/utils/const.ts +115 -0
- package/src/shopify/utils/cookie.ts +28 -0
- package/src/shopify/utils/errors.ts +65 -0
- package/src/shopify/utils/fetch-graphql-api.ts +67 -0
- package/src/shopify/utils/handle-fetch-response.ts +60 -0
- package/src/shopify/utils/helper.ts +89 -0
- package/src/shopify/utils/normalize/cart.ts +106 -0
- package/src/shopify/utils/normalize/customer.ts +18 -0
- package/src/shopify/utils/normalize/index.ts +2 -0
- package/src/shopify/utils/normalize/metafield.ts +69 -0
- package/src/shopify/utils/normalize/product.ts +193 -0
- package/src/shopify/utils/store.ts +5 -0
- package/src/shopify/utils/type-helper.ts +7 -0
- package/tsconfig.json +20 -0
- package/tsup.config.ts +17 -0
- package/dist/index.esm.js +0 -1669
- package/dist/index.js +0 -1679
- package/dist/index.mjs +0 -1669
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/shopify/utils/errors.ts"],
|
|
4
|
+
"sourcesContent": ["export type ErrorData = {\n message: string\n code?: string\n}\n\nexport type ErrorProps = {\n code?: string\n} & (\n | { message: string; errors?: never }\n | { message?: never; errors: ErrorData[] }\n)\n\nexport class CommerceError extends Error {\n code?: string\n errors: ErrorData[]\n\n constructor({ message, code, errors }: ErrorProps) {\n const error: ErrorData = message\n ? { message, ...(code ? { code } : {}) }\n : errors![0]\n\n super(error.message)\n this.errors = message ? [error] : errors!\n\n if (error.code) this.code = error.code\n }\n}\n\n// Used for errors that come from a bad implementation of the hooks\nexport class ValidationError extends CommerceError {\n constructor(options: ErrorProps) {\n super(options)\n }\n}\n\nexport class CommerceFetcherError extends CommerceError {\n status: number\n\n constructor(\n options: {\n status: number\n } & ErrorProps\n ) {\n super(options)\n this.status = options.status\n }\n}\n\nexport class FetcherError extends Error {\n status: number\n errors: string[]\n errorCode: string\n constructor(options: {\n status: number\n errors?: string[]\n message?: string\n errorCode?: string\n }) {\n const errorMessage = options.message || options.errors?.join('\\n')\n super(errorMessage)\n this.status = options.status\n this.errors = options.errors || []\n this.errorCode = options.errorCode || ''\n }\n}\n"],
|
|
5
|
+
"mappings": "wKAYO,MAAMA,UAAsB,KAAM,CAIvC,YAAY,CAAE,QAAAC,EAAS,KAAAC,EAAM,OAAAC,CAAO,EAAe,CACjD,MAAMC,EAAmBH,EACrB,CAAE,QAAAA,EAAS,GAAIC,EAAO,CAAE,KAAAA,CAAK,EAAI,CAAC,CAAG,EACrCC,EAAQ,CAAC,EAEb,MAAMC,EAAM,OAAO,EARrBC,EAAA,aACAA,EAAA,eAQE,KAAK,OAASJ,EAAU,CAACG,CAAK,EAAID,EAE9BC,EAAM,OAAM,KAAK,KAAOA,EAAM,KACpC,CACF,CAGO,MAAME,UAAwBN,CAAc,CACjD,YAAYO,EAAqB,CAC/B,MAAMA,CAAO,CACf,CACF,CAEO,MAAMC,UAA6BR,CAAc,CAGtD,YACEO,EAGA,CACA,MAAMA,CAAO,EAPfF,EAAA,eAQE,KAAK,OAASE,EAAQ,MACxB,CACF,CAEO,MAAME,UAAqB,KAAM,CAItC,YAAYF,EAKT,CACD,MAAMG,EAAeH,EAAQ,SAAWA,EAAQ,QAAQ,KAAK;AAAA,CAAI,EACjE,MAAMG,CAAY,EAVpBL,EAAA,eACAA,EAAA,eACAA,EAAA,kBASE,KAAK,OAASE,EAAQ,OACtB,KAAK,OAASA,EAAQ,QAAU,CAAC,EACjC,KAAK,UAAYA,EAAQ,WAAa,EACxC,CACF",
|
|
6
|
+
"names": ["CommerceError", "message", "code", "errors", "error", "__publicField", "ValidationError", "options", "CommerceFetcherError", "FetcherError", "errorMessage"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import m from"fetch-ponyfill";import{getCommerceError as d}from"../utils/handle-fetch-response";const{fetch:l}=m();async function w({query:o,variables:s,fetchOptions:i,headers:h,config:p}){const{storefrontToken:f,storeDomain:a}=p;let t;try{t=await l(`https://${a}/api/2025-07/graphql.json`,{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":f,...h},body:JSON.stringify({...o&&{query:o},...s&&{variables:s}}),...i});const{data:r,errors:e,status:n}=await t.json();if(e?.length)throw new Error(`Status: ${n}, ${t.status}, GraphQL errors: `+e.map(({message:c})=>c).join(", "));return{data:r,status:n,...e&&{errors:e}}}catch(r){throw console.error("fetchGraphqlApi url:",a,t?.status),d([{message:`status: ${t?.status}, ${r.message}
|
|
2
|
+
Most likely related to an unexpected output. e.g the store might be protected with password or not available.`}],500)}}export{w as fetchGraphqlApi};
|
|
3
|
+
//# sourceMappingURL=fetch-graphql-api.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/shopify/utils/fetch-graphql-api.ts"],
|
|
4
|
+
"sourcesContent": ["import fetchPonyfill from 'fetch-ponyfill'\nimport { ShopifyConfig } from '../types/config'\n\nimport { getCommerceError } from '../utils/handle-fetch-response'\n\nconst { fetch } = fetchPonyfill()\n\n/**\n * Graphql Api \u63A5\u53E3 fetch \u65B9\u6CD5\n * @param query: \u67E5\u8BE2\u8BED\u53E5\n * @param variables: \u67E5\u8BE2\u53C2\u6570\n * @param config: \u5E97\u94FA\u914D\u7F6E\n * @returns\n */\nexport async function fetchGraphqlApi<Data, Variables = undefined>({\n query,\n variables,\n fetchOptions,\n headers,\n config,\n}: {\n query: string\n variables?: Variables\n headers?: Record<string, any>\n fetchOptions?: Omit<RequestInit, 'headers' | 'method' | 'body'>\n config: ShopifyConfig\n}): Promise<{ status: number; data: Data; errors?: any } | never> {\n const { storefrontToken, storeDomain } = config\n\n let result: Response | undefined\n try {\n result = await fetch(`https://${storeDomain}/api/2025-07/graphql.json`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Shopify-Storefront-Access-Token': storefrontToken,\n ...headers,\n },\n body: JSON.stringify({\n ...(query && { query }),\n ...(variables && { variables }),\n }),\n ...fetchOptions,\n })\n\n const { data, errors, status } = await result.json()\n\n if (errors?.length) {\n throw new Error(\n `Status: ${status}, ${result.status}, GraphQL errors: ` +\n errors.map(({ message }: { message: string }) => message).join(', ')\n )\n }\n\n return { data, status, ...(errors && { errors }) }\n } catch (err: any) {\n console.error('fetchGraphqlApi url:', storeDomain, result?.status)\n throw getCommerceError(\n [\n {\n message: `status: ${result?.status}, ${err.message} \\n Most likely related to an unexpected output. e.g the store might be protected with password or not available.`,\n },\n ],\n 500\n )\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAOA,MAAmB,iBAG1B,OAAS,oBAAAC,MAAwB,iCAEjC,KAAM,CAAE,MAAAC,CAAM,EAAIF,EAAc,EAShC,eAAsBG,EAA6C,CACjE,MAAAC,EACA,UAAAC,EACA,aAAAC,EACA,QAAAC,EACA,OAAAC,CACF,EAMkE,CAChE,KAAM,CAAE,gBAAAC,EAAiB,YAAAC,CAAY,EAAIF,EAEzC,IAAIG,EACJ,GAAI,CACFA,EAAS,MAAMT,EAAM,WAAWQ,CAAW,4BAA6B,CACtE,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,oCAAqCD,EACrC,GAAGF,CACL,EACA,KAAM,KAAK,UAAU,CACnB,GAAIH,GAAS,CAAE,MAAAA,CAAM,EACrB,GAAIC,GAAa,CAAE,UAAAA,CAAU,CAC/B,CAAC,EACD,GAAGC,CACL,CAAC,EAED,KAAM,CAAE,KAAAM,EAAM,OAAAC,EAAQ,OAAAC,CAAO,EAAI,MAAMH,EAAO,KAAK,EAEnD,GAAIE,GAAQ,OACV,MAAM,IAAI,MACR,WAAWC,CAAM,KAAKH,EAAO,MAAM,qBACjCE,EAAO,IAAI,CAAC,CAAE,QAAAE,CAAQ,IAA2BA,CAAO,EAAE,KAAK,IAAI,CACvE,EAGF,MAAO,CAAE,KAAAH,EAAM,OAAAE,EAAQ,GAAID,GAAU,CAAE,OAAAA,CAAO,CAAG,CACnD,OAASG,EAAU,CACjB,cAAQ,MAAM,uBAAwBN,EAAaC,GAAQ,MAAM,EAC3DV,EACJ,CACE,CACE,QAAS,WAAWU,GAAQ,MAAM,KAAKK,EAAI,OAAO;AAAA,+GACpD,CACF,EACA,GACF,CACF,CACF",
|
|
6
|
+
"names": ["fetchPonyfill", "getCommerceError", "fetch", "fetchGraphqlApi", "query", "variables", "fetchOptions", "headers", "config", "storefrontToken", "storeDomain", "result", "data", "errors", "status", "message", "err"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{CommerceFetcherError as n,FetcherError as o}from"./errors";function g(r,e=500){return r=r??[{message:"Failed to fetch Shopify API"}],new n({errors:r,status:e})}async function c(r,e,t){let a="",s=[];return typeof r=="string"?a=r:Array.isArray(r)&&(s=r),new o({message:a,errors:s,status:e,errorCode:t||""})}async function i(r,e){return c(e?.errors||e?.message||(Array.isArray(e?.data.message)?e?.data.message.join(". "):e?.data.message)||e?.data?.error||r.statusText,r.status,e?.data?.error_code||"")}const m=async r=>{const e=await r.text();let t,a;if(e)try{t=JSON.parse(e),a=t?.error||t?.data?.error}catch{}if(r.ok&&!a)return t?.data||t;throw await i(r,t)};export{i as getAsyncError,g as getCommerceError,c as getFetcherError,m as handleFetchResponse};
|
|
2
|
+
//# sourceMappingURL=handle-fetch-response.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/shopify/utils/handle-fetch-response.ts"],
|
|
4
|
+
"sourcesContent": ["import { CommerceFetcherError, FetcherError } from './errors'\n\nexport function getCommerceError(errors: any[] | null, status = 500) {\n errors = errors ?? [{ message: 'Failed to fetch Shopify API' }]\n return new CommerceFetcherError({ errors, status })\n}\n\nexport async function getFetcherError(\n error: string | string[],\n statusCode: any,\n errorCode: any\n) {\n let message = '',\n errors: string[] = []\n if (typeof error === 'string') {\n message = error\n } else if (Array.isArray(error)) {\n errors = error\n }\n\n return new FetcherError({\n message,\n errors,\n status: statusCode,\n errorCode: errorCode || '',\n })\n}\n\nexport async function getAsyncError(res: Response, responseData: any) {\n return getFetcherError(\n responseData?.errors ||\n responseData?.message ||\n (Array.isArray(responseData?.data.message)\n ? responseData?.data.message.join('. ')\n : responseData?.data.message) ||\n responseData?.data?.error ||\n res.statusText,\n res.status,\n responseData?.data?.error_code || ''\n )\n}\n\nexport const handleFetchResponse = async (res: Response) => {\n const responseText = await res.text()\n let responseData\n let requestErrorMessage\n\n if (responseText) {\n try {\n responseData = JSON.parse(responseText)\n requestErrorMessage = responseData?.error || responseData?.data?.error\n } catch (err) {}\n }\n\n if (res.ok && !requestErrorMessage) {\n return responseData?.data || responseData\n }\n\n throw await getAsyncError(res, responseData)\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAS,wBAAAA,EAAsB,gBAAAC,MAAoB,WAE5C,SAASC,EAAiBC,EAAsBC,EAAS,IAAK,CACnE,OAAAD,EAASA,GAAU,CAAC,CAAE,QAAS,6BAA8B,CAAC,EACvD,IAAIH,EAAqB,CAAE,OAAAG,EAAQ,OAAAC,CAAO,CAAC,CACpD,CAEA,eAAsBC,EACpBC,EACAC,EACAC,EACA,CACA,IAAIC,EAAU,GACZN,EAAmB,CAAC,EACtB,OAAI,OAAOG,GAAU,SACnBG,EAAUH,EACD,MAAM,QAAQA,CAAK,IAC5BH,EAASG,GAGJ,IAAIL,EAAa,CACtB,QAAAQ,EACA,OAAAN,EACA,OAAQI,EACR,UAAWC,GAAa,EAC1B,CAAC,CACH,CAEA,eAAsBE,EAAcC,EAAeC,EAAmB,CACpE,OAAOP,EACLO,GAAc,QACZA,GAAc,UACb,MAAM,QAAQA,GAAc,KAAK,OAAO,EACrCA,GAAc,KAAK,QAAQ,KAAK,IAAI,EACpCA,GAAc,KAAK,UACvBA,GAAc,MAAM,OACpBD,EAAI,WACNA,EAAI,OACJC,GAAc,MAAM,YAAc,EACpC,CACF,CAEO,MAAMC,EAAsB,MAAOF,GAAkB,CAC1D,MAAMG,EAAe,MAAMH,EAAI,KAAK,EACpC,IAAIC,EACAG,EAEJ,GAAID,EACF,GAAI,CACFF,EAAe,KAAK,MAAME,CAAY,EACtCC,EAAsBH,GAAc,OAASA,GAAc,MAAM,KACnE,MAAc,CAAC,CAGjB,GAAID,EAAI,IAAM,CAACI,EACb,OAAOH,GAAc,MAAQA,EAG/B,MAAM,MAAMF,EAAcC,EAAKC,CAAY,CAC7C",
|
|
6
|
+
"names": ["CommerceFetcherError", "FetcherError", "getCommerceError", "errors", "status", "getFetcherError", "error", "statusCode", "errorCode", "message", "getAsyncError", "res", "responseData", "handleFetchResponse", "responseText", "requestErrorMessage"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import n from"js-cookie";import{CouponChannel as f}from"../utils/const";function v(e){return e?Object.keys(e).length===0:!0}function P(e){return e&&typeof e=="string"&&e.includes("/")?e.split("/").pop()?.split("?")?.shift():e}function k(e,t="ProductVariant"){return`gid://shopify/${t}/${e}`}const x=e=>e==="eu-de"?"de":e==="eu-en"?"eu":e==="au"?"au":e;function H(e={},t=""){return Object.entries(e).reduce((o,[s,d])=>{const a=d;return o[`${s}MetafieldIdentifiers`]=a.filter(i=>i.namespace!==t).map(i=>({namespace:t,key:i.namespace})).concat(a),o},{})}const R=()=>{const e=n.get("invite_code"),t=n.get("playModeId"),r=n.get("_popup");return e&&t?r?[{key:"_invite_code",value:e||""},{key:"_play_mode_id",value:t||""},{key:"_popup",value:r}]:[{key:"_invite_code",value:e||""},{key:"_play_mode_id",value:t||""}]:[]},C=({variant:e})=>e?.coupons?.find(t=>t.discount_type!==f.WSCH);export{P as atobID,k as btoaID,H as constructMetafieldIdentifiersQueryParams,C as getNormalCoupon,x as getThemeLocale,v as isObjEmpty,R as referralAttributes};
|
|
2
|
+
//# sourceMappingURL=helper.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/shopify/utils/helper.ts"],
|
|
4
|
+
"sourcesContent": ["import { HasMetafieldsIdentifier } from '../gql'\nimport { HasMetafieldQueryRoot } from '../types/fetcher'\nimport { PartialRecord } from '../utils/type-helper'\nimport Cookies from 'js-cookie'\nimport { CouponChannel } from '../utils/const'\nimport { ProductVariant } from '../types/product'\n\n// \u5224\u65AD\u5BF9\u8C61\u662F\u5426\u4E3A\u7A7A\nexport function isObjEmpty(obj?: Record<string, any>) {\n if (!obj) return true\n else {\n return Object.keys(obj).length === 0\n }\n}\n\nexport function atobID(id: string) {\n if (id && typeof id === 'string' && id.includes('/')) {\n return id.split('/').pop()?.split('?')?.shift()\n } else {\n return id\n }\n}\n\nexport function btoaID(id: string, type: 'ProductVariant' | 'Product' = 'ProductVariant') {\n return `gid://shopify/${type}/${id}`\n}\n\n// \u76AE\u80A4\u7AD9\u4E09\u7EA7\u57DF\u540D\nexport const getThemeLocale = (locale: string) => {\n if (locale === 'eu-de') return 'de'\n if (locale === 'eu-en') return 'eu'\n if (locale === 'au') return 'au'\n return locale\n}\n\n/**\n * \u751F\u6210 metafieldIdentifiers \u67E5\u8BE2\u53C2\u6570\n * {\n * product: { namespace: 'product', key: 'img' },\n * variant: { namespace: 'variant', key: 'img' }\n * }\n * =>\n * {\n * productMetafieldIdentifiers: [{ namespace: 'combo', key: 'product' }]\n * variantMetafieldIdentifiers: [{ namespace: 'combo', key: 'variant' }]\n * }\n */\nexport function constructMetafieldIdentifiersQueryParams<T extends HasMetafieldQueryRoot>(\n metafieldIdentifiers: PartialRecord<T, HasMetafieldsIdentifier[]> = {},\n metafieldsNamespace: string = ''\n): PartialRecord<`${T}MetafieldIdentifiers`, HasMetafieldsIdentifier[]> {\n const identifiers = Object.entries(metafieldIdentifiers).reduce<\n PartialRecord<`${T}MetafieldIdentifiers`, HasMetafieldsIdentifier[]>\n >((queryInput, [key, value]) => {\n const metafieldIdentifiers = value as HasMetafieldsIdentifier[]\n queryInput[`${key}MetafieldIdentifiers` as `${T}MetafieldIdentifiers`] = metafieldIdentifiers\n .filter(item => item.namespace !== metafieldsNamespace)\n .map(item => ({\n namespace: metafieldsNamespace,\n key: item.namespace,\n }))\n .concat(metafieldIdentifiers)\n return queryInput\n }, {})\n return identifiers\n}\n\nexport const referralAttributes = () => {\n const inviteCode = Cookies.get('invite_code')\n const playModeId = Cookies.get('playModeId')\n const popup = Cookies.get('_popup')\n if (inviteCode && playModeId) {\n return popup\n ? [\n { key: '_invite_code', value: inviteCode ? inviteCode : '' },\n { key: '_play_mode_id', value: playModeId ? playModeId : '' },\n { key: '_popup', value: popup },\n ]\n : [\n { key: '_invite_code', value: inviteCode ? inviteCode : '' },\n { key: '_play_mode_id', value: playModeId ? playModeId : '' },\n ]\n }\n return []\n}\n\nexport const getNormalCoupon = ({ variant }: { variant?: ProductVariant }) => {\n return variant?.coupons?.find((coupon: any) => coupon.discount_type !== CouponChannel.WSCH)\n}\n"],
|
|
5
|
+
"mappings": "AAGA,OAAOA,MAAa,YACpB,OAAS,iBAAAC,MAAqB,iBAIvB,SAASC,EAAWC,EAA2B,CACpD,OAAKA,EAEI,OAAO,KAAKA,CAAG,EAAE,SAAW,EAFpB,EAInB,CAEO,SAASC,EAAOC,EAAY,CACjC,OAAIA,GAAM,OAAOA,GAAO,UAAYA,EAAG,SAAS,GAAG,EAC1CA,EAAG,MAAM,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,GAAG,MAAM,EAEvCA,CAEX,CAEO,SAASC,EAAOD,EAAYE,EAAqC,iBAAkB,CACxF,MAAO,iBAAiBA,CAAI,IAAIF,CAAE,EACpC,CAGO,MAAMG,EAAkBC,GACzBA,IAAW,QAAgB,KAC3BA,IAAW,QAAgB,KAC3BA,IAAW,KAAa,KACrBA,EAeF,SAASC,EACdC,EAAoE,CAAC,EACrEC,EAA8B,GACwC,CActE,OAboB,OAAO,QAAQD,CAAoB,EAAE,OAEvD,CAACE,EAAY,CAACC,EAAKC,CAAK,IAAM,CAC9B,MAAMJ,EAAuBI,EAC7B,OAAAF,EAAW,GAAGC,CAAG,sBAAoD,EAAIH,EACtE,OAAOK,GAAQA,EAAK,YAAcJ,CAAmB,EACrD,IAAII,IAAS,CACZ,UAAWJ,EACX,IAAKI,EAAK,SACZ,EAAE,EACD,OAAOL,CAAoB,EACvBE,CACT,EAAG,CAAC,CAAC,CAEP,CAEO,MAAMI,EAAqB,IAAM,CACtC,MAAMC,EAAalB,EAAQ,IAAI,aAAa,EACtCmB,EAAanB,EAAQ,IAAI,YAAY,EACrCoB,EAAQpB,EAAQ,IAAI,QAAQ,EAClC,OAAIkB,GAAcC,EACTC,EACH,CACE,CAAE,IAAK,eAAgB,MAAOF,GAA0B,EAAG,EAC3D,CAAE,IAAK,gBAAiB,MAAOC,GAA0B,EAAG,EAC5D,CAAE,IAAK,SAAU,MAAOC,CAAM,CAChC,EACA,CACE,CAAE,IAAK,eAAgB,MAAOF,GAA0B,EAAG,EAC3D,CAAE,IAAK,gBAAiB,MAAOC,GAA0B,EAAG,CAC9D,EAEC,CAAC,CACV,EAEaE,EAAkB,CAAC,CAAE,QAAAC,CAAQ,IACjCA,GAAS,SAAS,KAAMC,GAAgBA,EAAO,gBAAkBtB,EAAc,IAAI",
|
|
6
|
+
"names": ["Cookies", "CouponChannel", "isObjEmpty", "obj", "atobID", "id", "btoaID", "type", "getThemeLocale", "locale", "constructMetafieldIdentifiersQueryParams", "metafieldIdentifiers", "metafieldsNamespace", "queryInput", "key", "value", "item", "referralAttributes", "inviteCode", "playModeId", "popup", "getNormalCoupon", "variant", "coupon"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{normalizeMetafields as p}from"./metafield";function I(t,o=""){const r=t.lines?.edges?.map(e=>a(e,o)),l=t?.discountAllocations?.reduce((e,n)=>Number(n?.discountedAmount?.amount)+e,0),[c,i]=r?.reduce(([e,n],s)=>[(s?.discountAllocations?.reduce((d,m)=>Number(m?.amount)+d,0)||0)+e,Number(s?.subtotalAmount)+n],[0,0])||[0,0];return{customAttributes:t.attributes,totalLineItemsDiscount:l+c,id:t.id,url:t.checkoutUrl,ready:!0,customerId:t?.buyerIdentity?.customer?.id||"",email:t?.buyerIdentity?.email||"",createdAt:t.createdAt,currency:{code:t.cost?.subtotalAmount?.currencyCode},taxesIncluded:t.cost?.totalTaxAmountEstimated,lineItems:t.lines?.edges?.map(e=>a(e,o)),subtotalPrice:t.cost?.subtotalAmount?.amount,totalPrice:t.cost?.totalAmount?.amount-(t.cost?.totalTaxAmount?.amount||0),totalTaxAmount:0,lineItemsSubtotalPrice:i,discountCodes:t.discountCodes||[],discountAllocations:t?.discountAllocations?.map(e=>({code:e?.code||e?.title||"",amount:e?.discountedAmount?.amount}))||[]}}function a({node:{id:t,merchandise:o,quantity:r,discountAllocations:l,attributes:c,cost:i}},e=""){const n=o?.price?.amount,s=o?.product?.title;return{id:t,name:s,quantity:r,variantId:String(o?.id),productId:String(o?.product?.id),totalAmount:i?.totalAmount?.amount,subtotalAmount:i?.subtotalAmount?.amount,discountAllocations:l?.map(u=>({code:u?.code||u?.title||"",amount:u?.discountedAmount?.amount}))||[],customAttributes:c?.map(u=>({key:u?.key||"",value:u?.value||""}))||[],variant:{id:String(o?.id),options:[],price:n,listPrice:o?.compareAtPrice?.amount,sku:o?.sku??"",name:o?.title,requiresShipping:o?.requiresShipping??!1,availableForSale:A({...o,price:o?.price}),quantityAvailable:o?.quantityAvailable||0,currentlyNotInStock:o?.currentlyNotInStock||!1,metafields:p(o.metafields,e)},product:o?.product,path:`/${o?.product?.handle}`,discounts:[],options:o?.title=="Default Title"?[]:o?.selectedOptions}}const A=t=>!(!t.availableForSale||!t.quantityAvailable&&!t.currentlyNotInStock||t.price?.amount>=999999999e-2);export{I as normalizeCart,a as normalizeLineItem};
|
|
2
|
+
//# sourceMappingURL=cart.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/shopify/utils/normalize/cart.ts"],
|
|
4
|
+
"sourcesContent": ["import { ProductVariant as ShopifyProductVariant, CartLine as ShopifyCartLine } from '../../gql'\nimport type { Cart, LineItem } from '../../types/cart'\nimport type { Cart as ShopifyCart } from '../../gql'\n\nimport { normalizeMetafields } from './metafield'\n\nexport function normalizeCart(cart: ShopifyCart, metafieldsNamespace: string = ''): Cart {\n const lineItems = cart.lines?.edges?.map(item => normalizeLineItem(item, metafieldsNamespace))\n const orderDiscounts = cart?.discountAllocations?.reduce((pre, cur) => {\n return Number(cur?.discountedAmount?.amount) + pre\n }, 0)\n const [totalLineItemsDiscount, lineItemsSubtotalPrice] = lineItems?.reduce(\n ([t, l], cur) => {\n const currentDiscount = cur?.discountAllocations?.reduce((p, c) => Number(c?.amount) + p, 0) || 0\n return [currentDiscount + t, Number(cur?.subtotalAmount) + l]\n },\n [0, 0]\n ) || [0, 0]\n\n return {\n customAttributes: cart.attributes,\n totalLineItemsDiscount: orderDiscounts + totalLineItemsDiscount,\n id: cart.id,\n url: cart.checkoutUrl,\n ready: true,\n customerId: cart?.buyerIdentity?.customer?.id || '',\n email: cart?.buyerIdentity?.email || '',\n createdAt: cart.createdAt,\n currency: {\n code: cart.cost?.subtotalAmount?.currencyCode,\n },\n taxesIncluded: cart.cost?.totalTaxAmountEstimated,\n lineItems: cart.lines?.edges?.map(item => normalizeLineItem(item, metafieldsNamespace)),\n subtotalPrice: cart.cost?.subtotalAmount?.amount,\n totalPrice: cart.cost?.totalAmount?.amount - (cart.cost?.totalTaxAmount?.amount || 0),\n // \u9884\u4F30\u7A0E\u989D\u73B0\u5728\u903B\u8F91\u6CA1\u7406\u6E05\u695A\uFF0C\u6682\u65F6 \u5199\u6B7B\u4E3A 0\n // totalTaxAmount: cart.cost?.totalTaxAmount?.amount,\n totalTaxAmount: 0,\n // lineItemsSubtotalPrice: cart.cost?.subtotalAmount?.amount,\n lineItemsSubtotalPrice,\n discountCodes: cart.discountCodes || [],\n discountAllocations:\n cart?.discountAllocations?.map(item => ({\n code: item?.code || item?.title || '',\n amount: item?.discountedAmount?.amount,\n })) || [],\n }\n}\n\nexport function normalizeLineItem({\n node: { id, merchandise: variant, quantity, discountAllocations, attributes, cost },\n}: {\n node: ShopifyCartLine\n}, metafieldNamespacePrefix: string = ''): LineItem {\n const price = variant?.price?.amount\n const name = variant?.product?.title\n return {\n id,\n name,\n quantity,\n variantId: String(variant?.id),\n productId: String(variant?.product?.id),\n totalAmount: cost?.totalAmount?.amount,\n subtotalAmount: cost?.subtotalAmount?.amount,\n discountAllocations:\n discountAllocations?.map(item => ({\n code: item?.code || item?.title || '',\n amount: item?.discountedAmount?.amount,\n })) || [],\n customAttributes:\n attributes?.map(item => ({\n key: item?.key || '',\n value: item?.value || '',\n })) || [],\n variant: {\n id: String(variant?.id),\n options: [],\n price,\n listPrice: variant?.compareAtPrice?.amount,\n sku: variant?.sku ?? '',\n name: variant?.title!,\n requiresShipping: variant?.requiresShipping ?? false,\n availableForSale: availableVariant({\n ...variant,\n price: variant?.price,\n } as unknown as ShopifyProductVariant),\n quantityAvailable: variant?.quantityAvailable || 0,\n currentlyNotInStock: variant?.currentlyNotInStock || false,\n metafields: normalizeMetafields(variant.metafields, metafieldNamespacePrefix),\n },\n product: variant?.product as any,\n path: `/${variant?.product?.handle}`,\n discounts: [],\n options: variant?.title == 'Default Title' ? [] : variant?.selectedOptions,\n }\n}\n\nconst availableVariant = (variant: ShopifyProductVariant) => {\n //availableForSale \u662F\u5426\u53EF\u552E true:\u53EF\u552E\n if (!variant.availableForSale) return false\n //currentlyNotInStock \u662F\u5426\u53EF\u8D85\u5356 true:\u662F\n //quantityAvailable \u5E93\u5B58\n if (!variant.quantityAvailable && !variant.currentlyNotInStock) return false\n if (variant.price?.amount >= 9999999.99) return false\n return true\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["normalizeMetafields", "normalizeCart", "cart", "metafieldsNamespace", "lineItems", "item", "normalizeLineItem", "orderDiscounts", "pre", "cur", "totalLineItemsDiscount", "lineItemsSubtotalPrice", "t", "l", "p", "c", "id", "variant", "quantity", "discountAllocations", "attributes", "cost", "metafieldNamespacePrefix", "price", "name", "availableVariant"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function N(e){const{id:t,firstName:a,lastName:r,displayName:s,email:o,phone:m,tags:i,acceptsMarketing:p,createdAt:n,orders:c}=e;return{id:t,firstName:a||"",lastName:r||"",displayName:s||"",email:o||"",phone:m||"",tags:i||[],acceptsMarketing:p||!1,createdAt:n||"",orders:c?.nodes?.map(d=>d)||[]}}export{N as normalizeCustomer};
|
|
2
|
+
//# sourceMappingURL=customer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/shopify/utils/normalize/customer.ts"],
|
|
4
|
+
"sourcesContent": ["import { Customer } from '../../types/customer'\nimport { Customer as ShopifyCustomer } from '../../gql'\n\nexport function normalizeCustomer(customer: ShopifyCustomer): Customer {\n const { id, firstName, lastName, displayName, email, phone, tags, acceptsMarketing, createdAt, orders } = customer\n return {\n id,\n firstName: firstName || '',\n lastName: lastName || '',\n displayName: displayName || '',\n email: email || '',\n phone: phone || '',\n tags: tags || [],\n acceptsMarketing: acceptsMarketing || false,\n createdAt: createdAt || '',\n orders: orders?.nodes?.map(order => order) || [],\n }\n}\n"],
|
|
5
|
+
"mappings": "AAGO,SAASA,EAAkBC,EAAqC,CACrE,KAAM,CAAE,GAAAC,EAAI,UAAAC,EAAW,SAAAC,EAAU,YAAAC,EAAa,MAAAC,EAAO,MAAAC,EAAO,KAAAC,EAAM,iBAAAC,EAAkB,UAAAC,EAAW,OAAAC,CAAO,EAAIV,EAC1G,MAAO,CACL,GAAAC,EACA,UAAWC,GAAa,GACxB,SAAUC,GAAY,GACtB,YAAaC,GAAe,GAC5B,MAAOC,GAAS,GAChB,MAAOC,GAAS,GAChB,KAAMC,GAAQ,CAAC,EACf,iBAAkBC,GAAoB,GACtC,UAAWC,GAAa,GACxB,OAAQC,GAAQ,OAAO,IAAIC,GAASA,CAAK,GAAK,CAAC,CACjD,CACF",
|
|
6
|
+
"names": ["normalizeCustomer", "customer", "id", "firstName", "lastName", "displayName", "email", "phone", "tags", "acceptsMarketing", "createdAt", "orders", "order"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const d=(e,n)=>e?.reduce((t,a)=>{if(a){let s=a.namespace;if(s.startsWith(`${n}combo`)){s=a.key,t[s]=t[s]||{};const o=r(a);o&&Object.entries(o).forEach(([c,i])=>{t[s][c]=t[s][c]??(i?r(i):null)})}else t[s]=t[s]||{},t[s][a.key]=a?r(a):null}return t},{});function l(e){try{return JSON.parse(e)}catch{return{}}}const u=e=>{const n=l(e)||{};return{parseType:n.type,descContent:n.content||"",status:n.status||"Active"}},r=e=>{const n=e?.type&&e?.type.toLowerCase(),{status:t}=u(e?.description||"");if(t.toLowerCase()!=="active")return null;switch(n){case"json":case"json_string":case"rating":case"volume":case"weight":case"dimension":return JSON.parse(e.value);default:return e?.value||e}};export{d as normalizeMetafields,l as parseJSON,r as parseMetafield};
|
|
2
|
+
//# sourceMappingURL=metafield.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/shopify/utils/normalize/metafield.ts"],
|
|
4
|
+
"sourcesContent": ["import { Maybe } from 'graphql/jsutils/Maybe'\nimport { Metafield } from '../../gql'\n\nexport const normalizeMetafields = (\n metafields: Maybe<Metafield>[], \n metafieldNamespacePrefix: string\n): Record<string, any> => {\n // combo namespace \u7684\u4F18\u5148\u7EA7\u4F4E\u4E8E\u666E\u901Anamespace\u7684\u4F18\u5148\u7EA7\n return metafields?.reduce(\n (prev, cur) => {\n if (cur) {\n let namespace = cur.namespace\n if (namespace.startsWith(`${metafieldNamespacePrefix}combo`)) {\n namespace = cur.key\n prev[namespace] = prev[namespace] || {}\n\n const parsedMetafields: {\n [key: string]: Metafield\n } = parseMetafield(cur)\n if (parsedMetafields) {\n Object.entries(parsedMetafields).forEach(([key, innerMetafields]) => {\n prev[namespace][key] = prev[namespace][key] ?? (innerMetafields ? parseMetafield(innerMetafields) : null)\n })\n }\n } else {\n prev[namespace] = prev[namespace] || {}\n prev[namespace][cur.key] = cur ? parseMetafield(cur) : null\n }\n }\n return prev\n },\n {} as Record<string, any>\n )\n}\n\nexport function parseJSON(str: string) {\n try {\n return JSON.parse(str)\n } catch (err) {\n return {}\n }\n}\n\nconst parseDesc = (desc: string) => {\n const cfg = parseJSON(desc) || {}\n return {\n parseType: cfg.type, // JSON_STRING\n descContent: cfg.content || '', // \u63CF\u8FF0\n status: cfg.status || 'Active', // \u72B6\u6001\n }\n}\n\nexport const parseMetafield = (metafield: Metafield) => {\n const type = metafield?.type && metafield?.type.toLowerCase()\n const { status } = parseDesc(metafield?.description || '')\n if (status.toLowerCase() !== 'active') return null\n\n switch (type) {\n case 'json':\n case 'json_string':\n case 'rating':\n case 'volume':\n case 'weight':\n case 'dimension':\n return JSON.parse(metafield.value)\n default:\n return metafield?.value || metafield\n }\n}\n"],
|
|
5
|
+
"mappings": "AAGO,MAAMA,EAAsB,CACjCC,EACAC,IAGOD,GAAY,OACjB,CAACE,EAAMC,IAAQ,CACb,GAAIA,EAAK,CACP,IAAIC,EAAYD,EAAI,UACpB,GAAIC,EAAU,WAAW,GAAGH,CAAwB,OAAO,EAAG,CAC5DG,EAAYD,EAAI,IAChBD,EAAKE,CAAS,EAAIF,EAAKE,CAAS,GAAK,CAAC,EAEtC,MAAMC,EAEFC,EAAeH,CAAG,EAClBE,GACF,OAAO,QAAQA,CAAgB,EAAE,QAAQ,CAAC,CAACE,EAAKC,CAAe,IAAM,CACnEN,EAAKE,CAAS,EAAEG,CAAG,EAAIL,EAAKE,CAAS,EAAEG,CAAG,IAAMC,EAAkBF,EAAeE,CAAe,EAAI,KACtG,CAAC,CAEL,MACEN,EAAKE,CAAS,EAAIF,EAAKE,CAAS,GAAK,CAAC,EACtCF,EAAKE,CAAS,EAAED,EAAI,GAAG,EAAIA,EAAMG,EAAeH,CAAG,EAAI,IAE3D,CACA,OAAOD,CACT,EACA,CAAC,CACH,EAGK,SAASO,EAAUC,EAAa,CACrC,GAAI,CACF,OAAO,KAAK,MAAMA,CAAG,CACvB,MAAc,CACZ,MAAO,CAAC,CACV,CACF,CAEA,MAAMC,EAAaC,GAAiB,CAClC,MAAMC,EAAMJ,EAAUG,CAAI,GAAK,CAAC,EAChC,MAAO,CACL,UAAWC,EAAI,KACf,YAAaA,EAAI,SAAW,GAC5B,OAAQA,EAAI,QAAU,QACxB,CACF,EAEaP,EAAkBQ,GAAyB,CACtD,MAAMC,EAAOD,GAAW,MAAQA,GAAW,KAAK,YAAY,EACtD,CAAE,OAAAE,CAAO,EAAIL,EAAUG,GAAW,aAAe,EAAE,EACzD,GAAIE,EAAO,YAAY,IAAM,SAAU,OAAO,KAE9C,OAAQD,EAAM,CACZ,IAAK,OACL,IAAK,cACL,IAAK,SACL,IAAK,SACL,IAAK,SACL,IAAK,YACH,OAAO,KAAK,MAAMD,EAAU,KAAK,EACnC,QACE,OAAOA,GAAW,OAASA,CAC/B,CACF",
|
|
6
|
+
"names": ["normalizeMetafields", "metafields", "metafieldNamespacePrefix", "prev", "cur", "namespace", "parsedMetafields", "parseMetafield", "key", "innerMetafields", "parseJSON", "str", "parseDesc", "desc", "cfg", "metafield", "type", "status"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{atobID as y}from"../helper";import{normalizeMetafields as g}from"./metafield";import{colorMap as C}from"../colors";const P=({amount:t,currencyCode:e})=>t&&e&&{amount:+t,currencyCode:e},b=t=>!(!t.availableForSale||!t.quantityAvailable&&!t.currentlyNotInStock||t.price?.amount>=999999999e-2),v=({id:t,name:e,values:s})=>({__typename:"ProductOption",id:t,name:e.toLowerCase(),values:s.map(a=>{let o={label:a};if(e.match(/colou?r/gi)){const i=C[a.toLowerCase().replace(/ /g,"")];i&&(o={...o,hexColors:[i]})}return o})}),h=({nodes:t})=>t?.map(e=>({url:e.url,alt:e.altText||""}))||[],V=({nodes:t})=>t?.map(e=>e)||[];function M(t,e=""){const{id:s,vendor:a,images:o,media:i,variants:u,handle:l,priceRange:c,options:d,metafields:p,availableForSale:f,...m}=t;return{...m,availableForSale:!!u.nodes.find(r=>!!r.availableForSale),id:s,vendor:a||"",handle:l,path:`/${l}`,slug:l?.replace(/^\/+|\/+$/g,""),price:P(c?.minVariantPrice),priceRange:c,images:h(o),media:V(i),options:d?d.filter(r=>r.name!=="Title").map(r=>v(r)):[],metafields:g(p,e)||{}}}const _=({metafields:t,variantId:e})=>t?.__discountCodeApp?.data?.filter(a=>{const o=String(a.variant_shopify_id)===y(e),i=(a.ends_at===null||new Date(a.ends_at).getTime()>new Date().getTime())&&(a.starts_at===null||new Date(a.starts_at).getTime()<=new Date().getTime());return o&&i})||[],I=({nodes:t},e,s="")=>t?.map(a=>{const{id:o,selectedOptions:i,sku:u,price:l,metafields:c,...d}=a,p=g(c,s),f=_({metafields:p,variantId:o});return{...d,id:o,sku:u??o,weight:a.weight,price:P(l),availableForSale:b(a),options:i.map(({name:m,value:r})=>v({id:o,name:m,values:[r]})),selectedOptions:i,metafields:p,product:M(e,s),coupons:f}});function q(t,e=""){const{id:s,vendor:a,images:o,media:i,variants:u,handle:l,priceRange:c,options:d,metafields:p,availableForSale:f,...m}=t,r=u?I(u,t,e):[];return{...m,availableForSale:!!r.find(n=>!!n.availableForSale),id:s,vendor:a||"",handle:l,path:`/${l}`,slug:l?.replace(/^\/+|\/+$/g,""),price:P(c?.minVariantPrice),priceRange:c,images:h(o),media:V(i),variants:r,options:d?.length>0?d.filter(n=>n.name!=="Title").map(n=>v(n)):r.length>1?[{id:"colorOptionsId",name:r?.[0]?.options?.[0]?.name,values:r.map(n=>n.options.map(S=>S.values)).flatMap(n=>n.flat())}]:[],metafields:g(p,e)||{}}}export{_ as getCouponsFromVariantMetafields,q as normalizeProduct,v as normalizeProductOption};
|
|
2
|
+
//# sourceMappingURL=product.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/shopify/utils/normalize/product.ts"],
|
|
4
|
+
"sourcesContent": ["\nimport {\n ImageConnection,\n MediaConnection,\n MoneyV2,\n Product as ShopifyProduct,\n ProductOption,\n ProductVariant as ShopifyProductVariant,\n ProductVariantConnection,\n SelectedOption,\n} from '../../gql'\nimport type {\n Product,\n ProductImage,\n ProductMedia,\n ProductPrice,\n ProductVariant,\n VariantCoupon,\n} from '../../types/product'\n\nimport { atobID } from '../helper'\nimport { normalizeMetafields } from './metafield'\nimport { colorMap } from '../colors'\n\nconst money = ({ amount, currencyCode }: MoneyV2): ProductPrice => {\n return (\n amount &&\n currencyCode && {\n amount: +amount,\n currencyCode,\n }\n )\n}\n\nconst checkVariantAvailable = (variant: ShopifyProductVariant) => {\n //availableForSale \u662F\u5426\u53EF\u552E true:\u53EF\u552E\n if (!variant.availableForSale) return false\n //currentlyNotInStock \u662F\u5426\u53EF\u8D85\u5356 true:\u662F\n //quantityAvailable \u5E93\u5B58\n if (!variant.quantityAvailable && !variant.currentlyNotInStock) return false\n if (variant.price?.amount >= 9999999.99) return false\n return true\n}\n\nexport const normalizeProductOption = ({\n id,\n name,\n values,\n}: ProductOption): {\n __typename: 'ProductOption'\n id: string\n name: string\n values: {\n label: string\n hexColors?: string[]\n }[]\n} => {\n return {\n __typename: 'ProductOption',\n id,\n name: name.toLowerCase(),\n values: values.map(value => {\n let output: any = {\n label: value,\n }\n if (name.match(/colou?r/gi)) {\n const mapedColor = colorMap[value.toLowerCase().replace(/ /g, '')]\n if (mapedColor) {\n output = {\n ...output,\n hexColors: [mapedColor],\n }\n }\n }\n return output\n }),\n }\n}\n\nconst normalizeProductImages = ({ nodes }: ImageConnection): ProductImage[] =>\n nodes?.map(node => ({\n url: node.url,\n alt: node.altText || '',\n })) || []\n\nconst normalizeProductMedia = ({ nodes }: MediaConnection): ProductMedia[] => nodes?.map(node => node) || []\n\n// variant \u4E0B\u7684 product \u4E0D\u5305\u542B variants\nfunction normalizeVariantProduct(product: ShopifyProduct, metafieldNamespacePrefix: string = ''): Omit<Product, 'variants'> {\n const { id, vendor, images, media, variants, handle, priceRange, options, metafields, availableForSale, ...rest } =\n product\n\n return {\n ...rest,\n availableForSale: !!variants.nodes.find(item => !!item.availableForSale),\n id,\n vendor: vendor || '',\n handle,\n path: `/${handle}`,\n slug: handle?.replace(/^\\/+|\\/+$/g, ''),\n price: money(priceRange?.minVariantPrice),\n priceRange,\n images: normalizeProductImages(images),\n media: normalizeProductMedia(media),\n options: options\n ? options\n .filter(o => o.name !== 'Title') // By default Shopify adds a 'Title' name when there's only one option. We don't need it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095\n .map(o => normalizeProductOption(o))\n : [],\n metafields: normalizeMetafields(metafields, metafieldNamespacePrefix) || {},\n }\n}\n\nexport const getCouponsFromVariantMetafields = ({ metafields, variantId }: { metafields: any; variantId: string }) => {\n const coupons =\n metafields?.__discountCodeApp?.data?.filter((coupon: VariantCoupon) => {\n const isRightVariant = String(coupon.variant_shopify_id) === atobID(variantId)\n\n const isActive =\n (coupon.ends_at === null || new Date(coupon.ends_at).getTime() > new Date().getTime()) &&\n (coupon.starts_at === null || new Date(coupon.starts_at).getTime() <= new Date().getTime())\n\n // \u539F by_skus \u7684\u63A5\u53E3\u9ED8\u8BA4\u4E0D\u8FD4\u56DE\u8FD9\u4E2A\u7C7B\u578B\u7684 code\n // const notWSCHCode = !coupon.title.toLocaleLowerCase().includes(CouponChannel.WSCH)\n\n return isRightVariant && isActive\n }) || []\n return coupons\n}\n\nconst normalizeProductVariants = ({ nodes }: ProductVariantConnection, product: ShopifyProduct, metafieldNamespacePrefix: string = ''): ProductVariant[] => {\n return nodes?.map(node => {\n const { id, selectedOptions, sku, price, metafields, ...rest } = node\n const normalizedMetafields = normalizeMetafields(metafields, metafieldNamespacePrefix)\n const coupons = getCouponsFromVariantMetafields({ metafields: normalizedMetafields, variantId: id })\n return {\n ...rest,\n id,\n sku: sku ?? id,\n weight: node.weight,\n price: money(price),\n availableForSale: checkVariantAvailable(node),\n options: selectedOptions.map(({ name, value }: SelectedOption) => {\n const options = normalizeProductOption({\n id,\n name,\n values: [value],\n })\n return options\n }),\n selectedOptions,\n metafields: normalizedMetafields,\n product: normalizeVariantProduct(product, metafieldNamespacePrefix),\n coupons,\n } as ProductVariant\n })\n}\n\nexport function normalizeProduct(product: ShopifyProduct, metafieldNamespacePrefix: string = ''): Product {\n const { id, vendor, images, media, variants, handle, priceRange, options, metafields, availableForSale, ...rest } =\n product\n\n const customVariants = variants ? normalizeProductVariants(variants, product, metafieldNamespacePrefix) : []\n return {\n ...rest,\n availableForSale: !!customVariants.find(item => !!item.availableForSale),\n id,\n vendor: vendor || '',\n handle,\n path: `/${handle}`,\n slug: handle?.replace(/^\\/+|\\/+$/g, ''),\n price: money(priceRange?.minVariantPrice),\n priceRange,\n images: normalizeProductImages(images),\n media: normalizeProductMedia(media),\n variants: customVariants,\n options:\n options?.length > 0\n ? options\n .filter(o => o.name !== 'Title') // By default Shopify adds a 'Title' name when there's only one option. We don't need it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095\n .map(o => normalizeProductOption(o))\n : customVariants.length > 1\n ? [\n {\n id: 'colorOptionsId',\n name: customVariants?.[0]?.options?.[0]?.name,\n values: customVariants.map(item => item.options.map(o => o.values)).flatMap(item => item.flat()),\n },\n ]\n : [],\n metafields: normalizeMetafields(metafields, metafieldNamespacePrefix) || {},\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["atobID", "normalizeMetafields", "colorMap", "money", "amount", "currencyCode", "checkVariantAvailable", "variant", "normalizeProductOption", "id", "name", "values", "value", "output", "mapedColor", "normalizeProductImages", "nodes", "node", "normalizeProductMedia", "normalizeVariantProduct", "product", "metafieldNamespacePrefix", "vendor", "images", "media", "variants", "handle", "priceRange", "options", "metafields", "availableForSale", "rest", "item", "o", "getCouponsFromVariantMetafields", "variantId", "coupon", "isRightVariant", "isActive", "normalizeProductVariants", "selectedOptions", "sku", "price", "normalizedMetafields", "coupons", "normalizeProduct", "customVariants"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/shopify/utils/store.ts"],
|
|
4
|
+
"sourcesContent": ["// \u8FD9\u4E2A\u6587\u4EF6\u73B0\u5728\u53EA\u4FDD\u7559 helper \u51FD\u6570\uFF0C\u5176\u4ED6\u529F\u80FD\u5DF2\u8FC1\u79FB\u5230 ShopifyContext\nimport { getThemeLocale } from './helper'\n\n// \u5BFC\u51FA helper \u51FD\u6570\u4F9B\u5176\u4ED6\u5730\u65B9\u4F7F\u7528\nexport { getThemeLocale }\n"],
|
|
5
|
+
"mappings": "AACA,OAAS,kBAAAA,MAAsB",
|
|
6
|
+
"names": ["getThemeLocale"]
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=type-helper.js.map
|
package/esbuild-cjs.mjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import esbuild from 'esbuild'
|
|
2
|
+
|
|
3
|
+
const dir = 'dist/cjs'
|
|
4
|
+
|
|
5
|
+
const options = {
|
|
6
|
+
entryPoints: ['src/**/*.ts*'],
|
|
7
|
+
outdir: dir,
|
|
8
|
+
format: 'cjs',
|
|
9
|
+
target: 'es2020',
|
|
10
|
+
sourcemap: true,
|
|
11
|
+
minify: true,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Check if "watch=true" flag is passed
|
|
15
|
+
if (process.argv[2]) {
|
|
16
|
+
const [key, value] = process.argv[2].split('=')
|
|
17
|
+
if (key === 'watch' && value === 'true') {
|
|
18
|
+
const ctx = await esbuild.context(options)
|
|
19
|
+
await ctx.watch()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
esbuild.build(options).catch(() => process.exit(1))
|
package/esbuild-esm.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import esbuild from 'esbuild'
|
|
2
|
+
const dir = 'dist/esm'
|
|
3
|
+
|
|
4
|
+
const options = {
|
|
5
|
+
entryPoints: ['src/**/*.ts*'],
|
|
6
|
+
outdir: dir,
|
|
7
|
+
format: 'esm',
|
|
8
|
+
target: 'es2020',
|
|
9
|
+
sourcemap: true,
|
|
10
|
+
minify: true,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Check if "watch=true" flag is passed
|
|
14
|
+
if (process.argv[2]) {
|
|
15
|
+
const [key, value] = process.argv[2].split('=')
|
|
16
|
+
if (key === 'watch' && value === 'true') {
|
|
17
|
+
const ctx = await esbuild.context(options)
|
|
18
|
+
await ctx.watch()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
esbuild.build(options).catch(() => process.exit(1))
|
|
23
|
+
|
|
24
|
+
// Create a package.json file in the dist/esm directory with "type": "module" field
|
|
25
|
+
import fs from 'fs'
|
|
26
|
+
import path from 'path'
|
|
27
|
+
if (!fs.existsSync(dir)) {
|
|
28
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
29
|
+
}
|
|
30
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ type: 'module' }, null, 2) + '\n', 'utf-8')
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { JestConfigWithTsJest } from 'ts-jest'
|
|
2
|
+
|
|
3
|
+
const config: JestConfigWithTsJest = {
|
|
4
|
+
preset: 'ts-jest',
|
|
5
|
+
testEnvironment: 'jsdom', // 使用 node 环境(如果是浏览器库可改成 'jsdom')
|
|
6
|
+
clearMocks: true, // 每次测试后自动清除 mock
|
|
7
|
+
coverageDirectory: 'coverage', // 输出覆盖率报告
|
|
8
|
+
testMatch: ['**/__tests__/**/*.test.ts'], // 匹配测试文件路径
|
|
9
|
+
moduleFileExtensions: ['ts', 'js', 'json'],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default config
|
package/package.json
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anker-in/lib",
|
|
3
|
-
"version": "0.0.0-beta.
|
|
3
|
+
"version": "0.0.0-beta.2",
|
|
4
4
|
"description": "Unified Anker headless library with shared context, Shopify integration, and cart utilities",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
5
|
+
"main": "./dist/cjs/index.js",
|
|
6
|
+
"module": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/esm/index.d.ts",
|
|
11
8
|
"exports": {
|
|
12
9
|
".": {
|
|
13
|
-
"import": {
|
|
14
|
-
"types": "./dist/index.d.mts",
|
|
15
|
-
"default": "./dist/index.mjs"
|
|
16
|
-
},
|
|
17
10
|
"require": {
|
|
18
|
-
"types": "./dist/index.d.ts",
|
|
19
|
-
"default": "./dist/index.js"
|
|
11
|
+
"types": "./dist/cjs/index.d.ts",
|
|
12
|
+
"default": "./dist/cjs/index.js"
|
|
13
|
+
},
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/esm/index.d.ts",
|
|
16
|
+
"default": "./dist/esm/index.js"
|
|
20
17
|
}
|
|
21
18
|
}
|
|
22
19
|
},
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SWRMutationConfiguration } from 'swr/mutation'
|
|
2
|
+
|
|
3
|
+
export const currencyCodeMapping = {
|
|
4
|
+
us: 'USD',
|
|
5
|
+
ca: 'CAD',
|
|
6
|
+
gb: 'GBP',
|
|
7
|
+
eu: 'EUR',
|
|
8
|
+
au: 'AUD',
|
|
9
|
+
nz: 'NZD',
|
|
10
|
+
de: 'EUR',
|
|
11
|
+
fr: 'EUR',
|
|
12
|
+
es: 'EUR',
|
|
13
|
+
it: 'EUR',
|
|
14
|
+
nl: 'EUR',
|
|
15
|
+
pl: 'EUR',
|
|
16
|
+
ro: 'EUR',
|
|
17
|
+
} as Record<string, string>
|
|
18
|
+
|
|
19
|
+
export const defaultSWRMutationConfiguration: SWRMutationConfiguration<any, any, any, any, any> & {
|
|
20
|
+
throwOnError?: boolean
|
|
21
|
+
} = {
|
|
22
|
+
throwOnError: false,
|
|
23
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Attributes, Cart, CartBuyerIdentity, CartInput } from '../../../shopify'
|
|
2
|
+
import { useCallback } from 'react'
|
|
3
|
+
import useSWRMutation, { SWRMutationConfiguration } from 'swr/mutation'
|
|
4
|
+
import { FbqBuyNowTrackConfig } from '../../track/fbq'
|
|
5
|
+
import { GtmParams, BuyNowLineItems } from '../../types'
|
|
6
|
+
// import { startInactiveSpan } from '@sentry/nextjs'
|
|
7
|
+
import { createCart as createCartFetcher } from '../../../shopify'
|
|
8
|
+
import { useHeadlessContext } from '../../../context'
|
|
9
|
+
import { defaultSWRMutationConfiguration } from '../../const'
|
|
10
|
+
|
|
11
|
+
type UseBuyNowProps = {
|
|
12
|
+
withTrack?: boolean // 是否需要默认埋点
|
|
13
|
+
redirectToCheckout?: boolean // 是否重定向到结账页
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type BuyNowArgs = {
|
|
17
|
+
lineItems: BuyNowLineItems
|
|
18
|
+
discountCodes?: string[]
|
|
19
|
+
customAttributes?: Attributes[]
|
|
20
|
+
buyerIdentity?: CartBuyerIdentity
|
|
21
|
+
gtmParams?: GtmParams
|
|
22
|
+
fbqTrackConfig?: FbqBuyNowTrackConfig
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const useBuyNow = (
|
|
26
|
+
{ withTrack = true, redirectToCheckout = true }: UseBuyNowProps = {},
|
|
27
|
+
swrOptions: SWRMutationConfiguration<Cart | undefined, Error, string, BuyNowArgs> & {
|
|
28
|
+
throwOnError?: boolean
|
|
29
|
+
} = defaultSWRMutationConfiguration
|
|
30
|
+
) => {
|
|
31
|
+
const { storefrontToken, storeDomain } = useHeadlessContext()
|
|
32
|
+
|
|
33
|
+
const trigger = useCallback(
|
|
34
|
+
async (_: any, { arg }: { arg: BuyNowArgs }) => {
|
|
35
|
+
const { lineItems, discountCodes, gtmParams = {}, buyerIdentity, fbqTrackConfig } = arg
|
|
36
|
+
|
|
37
|
+
if (!lineItems) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// const buyNowSpan = startInactiveSpan({
|
|
42
|
+
// name: 'buyNow',
|
|
43
|
+
// op: 'business',
|
|
44
|
+
// })
|
|
45
|
+
|
|
46
|
+
const linesToBuyNow = lineItems
|
|
47
|
+
.map(item => ({
|
|
48
|
+
merchandiseId: item.variant.id,
|
|
49
|
+
quantity: item.quantity || 1,
|
|
50
|
+
attributes: item.attributes,
|
|
51
|
+
}))
|
|
52
|
+
.filter(item => item.merchandiseId && item.quantity)
|
|
53
|
+
|
|
54
|
+
let resultCart: Cart | undefined
|
|
55
|
+
if (linesToBuyNow.length > 0) {
|
|
56
|
+
// const buyNowAPISpan = startInactiveSpan({
|
|
57
|
+
// name: 'buyNowAPI',
|
|
58
|
+
// op: 'business',
|
|
59
|
+
// parentSpan: buyNowSpan,
|
|
60
|
+
// })
|
|
61
|
+
|
|
62
|
+
// const createCartApiSpan = startInactiveSpan({
|
|
63
|
+
// name: 'createCartAPI',
|
|
64
|
+
// op: 'business',
|
|
65
|
+
// parentSpan: buyNowAPISpan,
|
|
66
|
+
// })
|
|
67
|
+
// 创建购物车
|
|
68
|
+
const createCartOptions = {
|
|
69
|
+
lines: linesToBuyNow,
|
|
70
|
+
buyerIdentity,
|
|
71
|
+
discountCodes,
|
|
72
|
+
} as CartInput
|
|
73
|
+
resultCart = await createCartFetcher({
|
|
74
|
+
options: createCartOptions,
|
|
75
|
+
config: {
|
|
76
|
+
storefrontToken,
|
|
77
|
+
storeDomain,
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
// createCartApiSpan.end()
|
|
81
|
+
|
|
82
|
+
// buyNowAPISpan.end()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 埋点
|
|
86
|
+
if (withTrack) {
|
|
87
|
+
// buyNowGa({ lineItems, router, gtmParams })
|
|
88
|
+
// if (fbqTrackConfig) {
|
|
89
|
+
// buyNowFbq({ router, trackConfig: fbqTrackConfig })
|
|
90
|
+
// }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// buyNowSpan.end()
|
|
94
|
+
if (redirectToCheckout && resultCart?.url) {
|
|
95
|
+
window.location.href = resultCart.url
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error('Failed to buy now')
|
|
98
|
+
}
|
|
99
|
+
return resultCart
|
|
100
|
+
},
|
|
101
|
+
[withTrack, redirectToCheckout, createCartFetcher]
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return useSWRMutation('buyNow', trigger, swrOptions)
|
|
105
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Context
|
|
2
|
+
|
|
3
|
+
// Basic Hooks
|
|
4
|
+
|
|
5
|
+
export * from './hooks/basic/useBuyNow'
|
|
6
|
+
|
|
7
|
+
// Feature Hooks
|
|
8
|
+
|
|
9
|
+
// Types
|
|
10
|
+
export * from './types'
|
|
11
|
+
|
|
12
|
+
// Utils
|
|
13
|
+
export * from './utils'
|
|
14
|
+
|
|
15
|
+
// Constants
|
|
16
|
+
export * from './const'
|
|
17
|
+
|
|
18
|
+
// Tracking
|
|
19
|
+
export * from './track/fbq'
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { AddToCartLineItems } from '../types'
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
fbq?: (...args: any) => void
|
|
6
|
+
gtag?: (...args: any) => void
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// facebook 埋点
|
|
11
|
+
export const fbq = (...args: any) => {
|
|
12
|
+
if (window.fbq) {
|
|
13
|
+
window.fbq(...args)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const gtag = (...args: any) => {
|
|
18
|
+
if (window.gtag) {
|
|
19
|
+
window.gtag(...args)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const addToCartFbq = ({ lineItems = [] }: { lineItems: AddToCartLineItems }) => {
|
|
24
|
+
if (lineItems.length && lineItems[0].variant) {
|
|
25
|
+
const { variant, quantity, finalPrice } = lineItems[0]
|
|
26
|
+
fbq('track', 'AddToCart', {
|
|
27
|
+
value: finalPrice?.amount || variant?.price?.amount,
|
|
28
|
+
num_items: quantity,
|
|
29
|
+
currency: variant?.price?.currencyCode,
|
|
30
|
+
content_name: variant?.product?.title, // 产品内容的名字
|
|
31
|
+
content_type: 'product_group',
|
|
32
|
+
content_ids: String(variant?.id), // 产品的varaint id
|
|
33
|
+
content_category: variant?.product?.metafields?.global?.trafficType || 'public', // 产品分类
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type FbqBuyNowTrackConfig = {
|
|
39
|
+
fbqBuyNowEvent: string
|
|
40
|
+
gtagBuyNowLabel: string
|
|
41
|
+
gtagBuyNowConversion: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const buyNowFbq = ({
|
|
45
|
+
trackConfig,
|
|
46
|
+
gtagId,
|
|
47
|
+
}: {
|
|
48
|
+
router: any
|
|
49
|
+
trackConfig: FbqBuyNowTrackConfig
|
|
50
|
+
gtagId: string
|
|
51
|
+
}) => {
|
|
52
|
+
try {
|
|
53
|
+
if (trackConfig?.fbqBuyNowEvent) {
|
|
54
|
+
fbq('trackCustom', trackConfig?.fbqBuyNowEvent)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (trackConfig?.gtagBuyNowLabel) {
|
|
58
|
+
gtag('event', trackConfig?.gtagBuyNowConversion || 'conversion', {
|
|
59
|
+
send_to: `${gtagId}/${trackConfig?.gtagBuyNowLabel}`,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {}
|
|
63
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Attributes } from '../../shopify'
|
|
2
|
+
import { ProductVariant, ProductPrice } from '../../shopify'
|
|
3
|
+
|
|
4
|
+
export type AddToCartLineItems = Array<{
|
|
5
|
+
variant: ProductVariant
|
|
6
|
+
variantId?: string // 兼容老数据
|
|
7
|
+
quantity: number
|
|
8
|
+
finalPrice?: ProductPrice
|
|
9
|
+
attributes?: Attributes
|
|
10
|
+
sellingPlanId?: string
|
|
11
|
+
}>
|
|
12
|
+
|
|
13
|
+
export type BuyNowLineItems = Array<{
|
|
14
|
+
variant: ProductVariant
|
|
15
|
+
quantity: number
|
|
16
|
+
finalPrice?: ProductPrice
|
|
17
|
+
attributes?: Attributes
|
|
18
|
+
sellingPlanId?: string
|
|
19
|
+
}>
|
|
20
|
+
|
|
21
|
+
export type GtmParams = {
|
|
22
|
+
position?: string // ga4 position
|
|
23
|
+
pageGroup?: string // ga4 pageGroup
|
|
24
|
+
ga4Params?: Record<string, any> // ga4 额外埋点字段
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Attributes } from '../../shopify'
|
|
2
|
+
|
|
3
|
+
export const isAttributesEqual = (oldAttributes: Attributes, newAttributes: Attributes) => {
|
|
4
|
+
// 比对两个数据是否完全相同
|
|
5
|
+
// 检查数组长度是否相同
|
|
6
|
+
if (oldAttributes?.length !== newAttributes?.length) {
|
|
7
|
+
return false
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// 将数组转换为 Map 以便快速查找
|
|
11
|
+
const oldMap = new Map(oldAttributes.map(attr => [attr.key, attr.value]))
|
|
12
|
+
const newMap = new Map(newAttributes.map(attr => [attr.key, attr.value]))
|
|
13
|
+
|
|
14
|
+
// 检查所有 key 是否都存在且值相同
|
|
15
|
+
for (const [key, value] of newMap) {
|
|
16
|
+
if (!oldMap.has(key) || oldMap.get(key) !== value) {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo, ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import { HeadlessConfig } from './config'
|
|
4
|
+
|
|
5
|
+
const HeadlessContext = createContext<HeadlessConfig | null>(null)
|
|
6
|
+
|
|
7
|
+
interface HeadlessProviderProps {
|
|
8
|
+
children: ReactNode
|
|
9
|
+
headlessConfig: HeadlessConfig
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const HeadlessProvider = ({ children, headlessConfig }: HeadlessProviderProps): JSX.Element => {
|
|
13
|
+
const contextValue = useMemo((): HeadlessConfig => {
|
|
14
|
+
if (!headlessConfig) {
|
|
15
|
+
throw new Error(`No site configuration or headless configuration found`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return headlessConfig
|
|
19
|
+
}, [headlessConfig])
|
|
20
|
+
|
|
21
|
+
return <HeadlessContext.Provider value={contextValue}>{children}</HeadlessContext.Provider>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const useHeadlessContext = (): HeadlessConfig => {
|
|
25
|
+
const context = useContext(HeadlessContext)
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error('useHeadlessContext must be used within a HeadlessProvider')
|
|
28
|
+
}
|
|
29
|
+
return context || ({} as HeadlessConfig)
|
|
30
|
+
}
|