@shopify/hydrogen 2024.7.6 → 2024.7.8

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.
@@ -511,7 +511,7 @@ var errorOnce = (string) => {
511
511
  };
512
512
 
513
513
  // src/version.ts
514
- var LIB_VERSION = "2024.7.6";
514
+ var LIB_VERSION = "2024.7.8";
515
515
 
516
516
  // src/utils/graphql.ts
517
517
  function minifyQuery(string) {
@@ -2337,7 +2337,7 @@ function redirect(path, options = {}) {
2337
2337
  async function refreshToken({
2338
2338
  session,
2339
2339
  customerAccountId,
2340
- customerAccountUrl,
2340
+ customerAccountTokenExchangeUrl,
2341
2341
  httpsOrigin,
2342
2342
  debugInfo,
2343
2343
  exchangeForStorefrontCustomerAccessToken
@@ -2360,7 +2360,7 @@ async function refreshToken({
2360
2360
  Origin: httpsOrigin
2361
2361
  };
2362
2362
  const startTime = (/* @__PURE__ */ new Date()).getTime();
2363
- const url = `${customerAccountUrl}/auth/oauth/token`;
2363
+ const url = customerAccountTokenExchangeUrl;
2364
2364
  const response = await fetch(url, {
2365
2365
  method: "POST",
2366
2366
  headers,
@@ -2390,7 +2390,7 @@ async function refreshToken({
2390
2390
  const accessToken = await exchangeAccessToken(
2391
2391
  access_token,
2392
2392
  customerAccountId,
2393
- customerAccountUrl,
2393
+ customerAccountTokenExchangeUrl,
2394
2394
  httpsOrigin,
2395
2395
  debugInfo
2396
2396
  );
@@ -2412,7 +2412,7 @@ async function checkExpires({
2412
2412
  expiresAt,
2413
2413
  session,
2414
2414
  customerAccountId,
2415
- customerAccountUrl,
2415
+ customerAccountTokenExchangeUrl,
2416
2416
  httpsOrigin,
2417
2417
  debugInfo,
2418
2418
  exchangeForStorefrontCustomerAccessToken
@@ -2423,7 +2423,7 @@ async function checkExpires({
2423
2423
  locks.refresh = refreshToken({
2424
2424
  session,
2425
2425
  customerAccountId,
2426
- customerAccountUrl,
2426
+ customerAccountTokenExchangeUrl,
2427
2427
  httpsOrigin,
2428
2428
  debugInfo,
2429
2429
  exchangeForStorefrontCustomerAccessToken
@@ -2474,7 +2474,7 @@ function generateState() {
2474
2474
  const randomString = Math.random().toString(36).substring(2);
2475
2475
  return timestamp + randomString;
2476
2476
  }
2477
- async function exchangeAccessToken(authAccessToken, customerAccountId, customerAccountUrl, httpsOrigin, debugInfo) {
2477
+ async function exchangeAccessToken(authAccessToken, customerAccountId, customerAccountTokenExchangeUrl, httpsOrigin, debugInfo) {
2478
2478
  const clientId = customerAccountId;
2479
2479
  if (!authAccessToken)
2480
2480
  throw new BadRequest(
@@ -2497,7 +2497,7 @@ async function exchangeAccessToken(authAccessToken, customerAccountId, customerA
2497
2497
  Origin: httpsOrigin
2498
2498
  };
2499
2499
  const startTime = (/* @__PURE__ */ new Date()).getTime();
2500
- const url = `${customerAccountUrl}/auth/oauth/token`;
2500
+ const url = customerAccountTokenExchangeUrl;
2501
2501
  const response = await fetch(url, {
2502
2502
  method: "POST",
2503
2503
  headers,
@@ -2547,6 +2547,30 @@ function toHexString(byteArray) {
2547
2547
  }).join("");
2548
2548
  }
2549
2549
 
2550
+ // src/customer/customer-account-helper.ts
2551
+ function createCustomerAccountHelper(customerApiVersion, deprecatedCustomerAccountUrl, shopId) {
2552
+ const customerAccountUrl = shopId ? `https://shopify.com/${shopId}` : deprecatedCustomerAccountUrl;
2553
+ const customerAccountAuthUrl = shopId ? `https://shopify.com/authentication/${shopId}` : `${deprecatedCustomerAccountUrl}/auth`;
2554
+ return function getCustomerAccountUrl(urlType) {
2555
+ switch (urlType) {
2556
+ case "CA_BASE_URL" /* CA_BASE_URL */:
2557
+ return customerAccountUrl;
2558
+ case "CA_BASE_AUTH_URL" /* CA_BASE_AUTH_URL */:
2559
+ return customerAccountAuthUrl;
2560
+ case "GRAPHQL" /* GRAPHQL */:
2561
+ return `${customerAccountUrl}/account/customer/api/${customerApiVersion}/graphql`;
2562
+ case "AUTH" /* AUTH */:
2563
+ return `${customerAccountAuthUrl}/oauth/authorize`;
2564
+ case "LOGIN_SCOPE" /* LOGIN_SCOPE */:
2565
+ return shopId ? "openid email customer-account-api:full" : "openid email https://api.customers.com/auth/customer.graphql";
2566
+ case "TOKEN_EXCHANGE" /* TOKEN_EXCHANGE */:
2567
+ return `${customerAccountAuthUrl}/oauth/token`;
2568
+ case "LOGOUT" /* LOGOUT */:
2569
+ return `${customerAccountAuthUrl}/logout`;
2570
+ }
2571
+ };
2572
+ }
2573
+
2550
2574
  // src/customer/customer.ts
2551
2575
  var DEFAULT_LOGIN_URL = "/account/login";
2552
2576
  var DEFAULT_AUTH_URL = "/account/authorize";
@@ -2560,7 +2584,8 @@ function defaultAuthStatusHandler(request) {
2560
2584
  function createCustomerAccountClient({
2561
2585
  session,
2562
2586
  customerAccountId,
2563
- customerAccountUrl,
2587
+ customerAccountUrl: deprecatedCustomerAccountUrl,
2588
+ shopId,
2564
2589
  customerApiVersion = DEFAULT_CUSTOMER_API_VERSION,
2565
2590
  request,
2566
2591
  waitUntil,
@@ -2584,6 +2609,11 @@ function createCustomerAccountClient({
2584
2609
  "[h2:error:createCustomerAccountClient] The request object does not contain a URL."
2585
2610
  );
2586
2611
  }
2612
+ if (!!deprecatedCustomerAccountUrl && !shopId) {
2613
+ warnOnce(
2614
+ "[h2:warn:createCustomerAccountClient] The `customerAccountUrl` option is deprecated and will be removed in a future version. Please remove `customerAccountUrl` and supply a `shopId: env.SHOP_ID` option instead.\n\nIf using `createHydrogenContext`, ensure there is a SHOP_ID defined in your local .env file."
2615
+ );
2616
+ }
2587
2617
  const authStatusHandler = customAuthStatusHandler ? customAuthStatusHandler : () => defaultAuthStatusHandler(request);
2588
2618
  const requestUrl = new URL(request.url);
2589
2619
  const httpsOrigin = requestUrl.protocol === "http:" ? requestUrl.origin.replace("http", "https") : requestUrl.origin;
@@ -2592,7 +2622,16 @@ function createCustomerAccountClient({
2592
2622
  defaultUrl: DEFAULT_AUTH_URL,
2593
2623
  redirectUrl: authUrl
2594
2624
  });
2595
- const customerAccountApiUrl = `${customerAccountUrl}/account/customer/api/${customerApiVersion}/graphql`;
2625
+ const getCustomerAccountUrl = createCustomerAccountHelper(
2626
+ customerApiVersion,
2627
+ deprecatedCustomerAccountUrl,
2628
+ shopId
2629
+ );
2630
+ const ifInvalidCredentialThrowError = createIfInvalidCredentialThrowError(
2631
+ getCustomerAccountUrl,
2632
+ customerAccountId
2633
+ );
2634
+ const customerAccountApiUrl = getCustomerAccountUrl("GRAPHQL" /* GRAPHQL */);
2596
2635
  const locks = {};
2597
2636
  async function fetchCustomerAPI({
2598
2637
  query: query2,
@@ -2667,7 +2706,8 @@ function createCustomerAccountClient({
2667
2706
  }
2668
2707
  }
2669
2708
  async function isLoggedIn() {
2670
- if (!customerAccountUrl || !customerAccountId) return false;
2709
+ if (!shopId && (!deprecatedCustomerAccountUrl || !customerAccountId))
2710
+ return false;
2671
2711
  const customerAccount = session.get(CUSTOMER_ACCOUNT_SESSION_KEY);
2672
2712
  const accessToken = customerAccount?.accessToken;
2673
2713
  const expiresAt = customerAccount?.expiresAt;
@@ -2679,7 +2719,9 @@ function createCustomerAccountClient({
2679
2719
  expiresAt,
2680
2720
  session,
2681
2721
  customerAccountId,
2682
- customerAccountUrl,
2722
+ customerAccountTokenExchangeUrl: getCustomerAccountUrl(
2723
+ "TOKEN_EXCHANGE" /* TOKEN_EXCHANGE */
2724
+ ),
2683
2725
  httpsOrigin,
2684
2726
  debugInfo: {
2685
2727
  waitUntil,
@@ -2704,7 +2746,7 @@ function createCustomerAccountClient({
2704
2746
  return session.get(CUSTOMER_ACCOUNT_SESSION_KEY)?.accessToken;
2705
2747
  }
2706
2748
  async function mutate(mutation, options) {
2707
- ifInvalidCredentialThrowError(customerAccountUrl, customerAccountId);
2749
+ ifInvalidCredentialThrowError();
2708
2750
  mutation = minifyQuery(mutation);
2709
2751
  assertMutation(mutation, "customer.mutate");
2710
2752
  return withSyncStack(
@@ -2713,7 +2755,7 @@ function createCustomerAccountClient({
2713
2755
  );
2714
2756
  }
2715
2757
  async function query(query2, options) {
2716
- ifInvalidCredentialThrowError(customerAccountUrl, customerAccountId);
2758
+ ifInvalidCredentialThrowError();
2717
2759
  query2 = minifyQuery(query2);
2718
2760
  assertQuery(query2, "customer.query");
2719
2761
  return withSyncStack(fetchCustomerAPI({ query: query2, type: "query", ...options }), {
@@ -2754,8 +2796,8 @@ function createCustomerAccountClient({
2754
2796
  }
2755
2797
  return {
2756
2798
  login: async (options) => {
2757
- ifInvalidCredentialThrowError(customerAccountUrl, customerAccountId);
2758
- const loginUrl = new URL(`${customerAccountUrl}/auth/oauth/authorize`);
2799
+ ifInvalidCredentialThrowError();
2800
+ const loginUrl = new URL(getCustomerAccountUrl("AUTH" /* AUTH */));
2759
2801
  const state = generateState();
2760
2802
  const nonce = generateNonce();
2761
2803
  loginUrl.searchParams.set("client_id", customerAccountId);
@@ -2764,7 +2806,7 @@ function createCustomerAccountClient({
2764
2806
  loginUrl.searchParams.append("redirect_uri", redirectUri);
2765
2807
  loginUrl.searchParams.set(
2766
2808
  "scope",
2767
- "openid email https://api.customers.com/auth/customer.graphql"
2809
+ getCustomerAccountUrl("LOGIN_SCOPE" /* LOGIN_SCOPE */)
2768
2810
  );
2769
2811
  loginUrl.searchParams.append("state", state);
2770
2812
  loginUrl.searchParams.append("nonce", nonce);
@@ -2790,7 +2832,7 @@ function createCustomerAccountClient({
2790
2832
  return redirect(loginUrl.toString());
2791
2833
  },
2792
2834
  logout: async (options) => {
2793
- ifInvalidCredentialThrowError(customerAccountUrl, customerAccountId);
2835
+ ifInvalidCredentialThrowError();
2794
2836
  const idToken = session.get(CUSTOMER_ACCOUNT_SESSION_KEY)?.idToken;
2795
2837
  const postLogoutRedirectUri = ensureLocalRedirectUrl({
2796
2838
  requestUrl: httpsOrigin,
@@ -2798,7 +2840,7 @@ function createCustomerAccountClient({
2798
2840
  redirectUrl: options?.postLogoutRedirectUri
2799
2841
  });
2800
2842
  const logoutUrl = idToken ? new URL(
2801
- `${customerAccountUrl}/auth/logout?${new URLSearchParams([
2843
+ `${getCustomerAccountUrl("LOGOUT" /* LOGOUT */)}?${new URLSearchParams([
2802
2844
  ["id_token_hint", idToken],
2803
2845
  ["post_logout_redirect_uri", postLogoutRedirectUri]
2804
2846
  ]).toString()}`
@@ -2813,7 +2855,7 @@ function createCustomerAccountClient({
2813
2855
  mutate,
2814
2856
  query,
2815
2857
  authorize: async () => {
2816
- ifInvalidCredentialThrowError(customerAccountUrl, customerAccountId);
2858
+ ifInvalidCredentialThrowError();
2817
2859
  const code = requestUrl.searchParams.get("code");
2818
2860
  const state = requestUrl.searchParams.get("state");
2819
2861
  if (!code || !state) {
@@ -2852,7 +2894,7 @@ function createCustomerAccountClient({
2852
2894
  };
2853
2895
  const stackInfo = getCallerStackLine?.();
2854
2896
  const startTime = (/* @__PURE__ */ new Date()).getTime();
2855
- const url = `${customerAccountUrl}/auth/oauth/token`;
2897
+ const url = getCustomerAccountUrl("TOKEN_EXCHANGE" /* TOKEN_EXCHANGE */);
2856
2898
  const response = await fetch(url, {
2857
2899
  method: "POST",
2858
2900
  headers,
@@ -2889,17 +2931,20 @@ function createCustomerAccountClient({
2889
2931
  `Returned nonce does not match: ${sessionNonce} !== ${responseNonce}`
2890
2932
  );
2891
2933
  }
2892
- const customerAccessToken = await exchangeAccessToken(
2893
- access_token,
2894
- customerAccountId,
2895
- customerAccountUrl,
2896
- httpsOrigin,
2897
- {
2898
- waitUntil,
2899
- stackInfo,
2900
- ...getDebugHeaders(request)
2901
- }
2902
- );
2934
+ let customerAccessToken = access_token;
2935
+ if (!shopId) {
2936
+ customerAccessToken = await exchangeAccessToken(
2937
+ access_token,
2938
+ customerAccountId,
2939
+ getCustomerAccountUrl("TOKEN_EXCHANGE" /* TOKEN_EXCHANGE */),
2940
+ httpsOrigin,
2941
+ {
2942
+ waitUntil,
2943
+ stackInfo,
2944
+ ...getDebugHeaders(request)
2945
+ }
2946
+ );
2947
+ }
2903
2948
  const redirectPath = session.get(
2904
2949
  CUSTOMER_ACCOUNT_SESSION_KEY
2905
2950
  )?.redirectPath;
@@ -2916,19 +2961,22 @@ function createCustomerAccountClient({
2916
2961
  UNSTABLE_getBuyer: getBuyer
2917
2962
  };
2918
2963
  }
2919
- function ifInvalidCredentialThrowError(customerAccountUrl, customerAccountId) {
2920
- try {
2921
- if (!customerAccountUrl || !customerAccountId) throw Error();
2922
- new URL(customerAccountUrl);
2923
- } catch {
2924
- console.error(
2925
- new Error(
2926
- "[h2:error:customerAccount] You do not have the valid credential to use Customer Account API.\nRun `h2 env pull` to link your store credentials."
2927
- )
2928
- );
2929
- const publicMessage = "You do not have the valid credential to use Customer Account API (/account).";
2930
- throw new Response(publicMessage, { status: 500 });
2931
- }
2964
+ function createIfInvalidCredentialThrowError(getCustomerAccountUrl, customerAccountId) {
2965
+ return function ifInvalidCredentialThrowError() {
2966
+ try {
2967
+ if (!customerAccountId) throw Error();
2968
+ new URL(getCustomerAccountUrl("CA_BASE_URL" /* CA_BASE_URL */));
2969
+ new URL(getCustomerAccountUrl("CA_BASE_AUTH_URL" /* CA_BASE_AUTH_URL */));
2970
+ } catch {
2971
+ console.error(
2972
+ new Error(
2973
+ "[h2:error:customerAccount] You do not have the valid credential to use Customer Account API.\nRun `h2 env pull` to link your store credentials."
2974
+ )
2975
+ );
2976
+ const publicMessage = "You do not have the valid credential to use Customer Account API (/account).";
2977
+ throw new Response(publicMessage, { status: 500 });
2978
+ }
2979
+ };
2932
2980
  }
2933
2981
 
2934
2982
  // src/changelogHandler.ts
@@ -4369,12 +4417,13 @@ function overrideCustomerPrivacySetTrackingConsent({
4369
4417
  config
4370
4418
  }) {
4371
4419
  const original = customerPrivacy.setTrackingConsent;
4420
+ const { locale, country, ...rest } = config;
4372
4421
  function updatedSetTrackingConsent(consent, callback) {
4373
4422
  original(
4374
4423
  {
4375
- ...consent,
4424
+ ...rest,
4376
4425
  headlessStorefront: true,
4377
- ...config
4426
+ ...consent
4378
4427
  },
4379
4428
  callback
4380
4429
  );
@@ -4419,7 +4468,7 @@ function getPrivacyBanner() {
4419
4468
  }
4420
4469
 
4421
4470
  // package.json
4422
- var version = "2024.7.6";
4471
+ var version = "2024.7.8";
4423
4472
 
4424
4473
  // src/analytics-manager/ShopifyAnalytics.tsx
4425
4474
  function getCustomerPrivacyRequired() {
@@ -5142,6 +5191,8 @@ function createHydrogenContext(options) {
5142
5191
  unstableB2b: customerAccountOptions?.unstableB2b,
5143
5192
  // defaults
5144
5193
  customerAccountId: env.PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID,
5194
+ shopId: env.SHOP_ID,
5195
+ // deprecated - keep until next major release
5145
5196
  customerAccountUrl: env.PUBLIC_CUSTOMER_ACCOUNT_API_URL
5146
5197
  });
5147
5198
  const cart = createCartHandler({