@shopify/cli-hydrogen 10.0.2 → 10.1.0

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.
@@ -1,5 +1,14 @@
1
1
  # skeleton
2
2
 
3
+ ## 2025.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Add a new tokenless Storefront API route to the starter template. ([#2948](https://github.com/Shopify/hydrogen/pull/2948)) by [@blittle](https://github.com/blittle)
8
+
9
+ - Updated dependencies [[`d44fab3d`](https://github.com/Shopify/hydrogen/commit/d44fab3d07c5e255edcd22745d4d7e2db2c3e60f)]:
10
+ - @shopify/hydrogen@2025.4.1
11
+
3
12
  ## 2025.4.0
4
13
 
5
14
  ### Patch Changes
@@ -164,13 +173,13 @@
164
173
  1. Add a routes.ts file. This is your new Remix route configuration file.
165
174
 
166
175
  ```ts
167
- import {flatRoutes} from '@remix-run/fs-routes';
168
- import {layout, type RouteConfig} from '@remix-run/route-config';
169
- import {hydrogenRoutes} from '@shopify/hydrogen';
176
+ import { flatRoutes } from "@remix-run/fs-routes";
177
+ import { layout, type RouteConfig } from "@remix-run/route-config";
178
+ import { hydrogenRoutes } from "@shopify/hydrogen";
170
179
 
171
180
  export default hydrogenRoutes([
172
181
  // Your entire app reading from routes folder using Layout from layout.tsx
173
- layout('./layout.tsx', await flatRoutes()),
182
+ layout("./layout.tsx", await flatRoutes()),
174
183
  ]) satisfies RouteConfig;
175
184
  ```
176
185
 
@@ -761,25 +770,25 @@
761
770
  8. Update the `ProductForm` component.
762
771
 
763
772
  ```tsx
764
- import {Link, useNavigate} from '@remix-run/react';
765
- import {type MappedProductOptions} from '@shopify/hydrogen';
773
+ import { Link, useNavigate } from "@remix-run/react";
774
+ import { type MappedProductOptions } from "@shopify/hydrogen";
766
775
  import type {
767
776
  Maybe,
768
777
  ProductOptionValueSwatch,
769
- } from '@shopify/hydrogen/storefront-api-types';
770
- import {AddToCartButton} from './AddToCartButton';
771
- import {useAside} from './Aside';
772
- import type {ProductFragment} from 'storefrontapi.generated';
778
+ } from "@shopify/hydrogen/storefront-api-types";
779
+ import { AddToCartButton } from "./AddToCartButton";
780
+ import { useAside } from "./Aside";
781
+ import type { ProductFragment } from "storefrontapi.generated";
773
782
 
774
783
  export function ProductForm({
775
784
  productOptions,
776
785
  selectedVariant,
777
786
  }: {
778
787
  productOptions: MappedProductOptions[];
779
- selectedVariant: ProductFragment['selectedOrFirstAvailableVariant'];
788
+ selectedVariant: ProductFragment["selectedOrFirstAvailableVariant"];
780
789
  }) {
781
790
  const navigate = useNavigate();
782
- const {open} = useAside();
791
+ const { open } = useAside();
783
792
  return (
784
793
  <div className="product-form">
785
794
  {productOptions.map((option) => (
@@ -813,8 +822,8 @@
813
822
  to={`/products/${handle}?${variantUriQuery}`}
814
823
  style={{
815
824
  border: selected
816
- ? '1px solid black'
817
- : '1px solid transparent',
825
+ ? "1px solid black"
826
+ : "1px solid transparent",
818
827
  opacity: available ? 1 : 0.3,
819
828
  }}
820
829
  >
@@ -831,13 +840,13 @@
831
840
  <button
832
841
  type="button"
833
842
  className={`product-options-item${
834
- exists && !selected ? ' link' : ''
843
+ exists && !selected ? " link" : ""
835
844
  }`}
836
845
  key={option.name + name}
837
846
  style={{
838
847
  border: selected
839
- ? '1px solid black'
840
- : '1px solid transparent',
848
+ ? "1px solid black"
849
+ : "1px solid transparent",
841
850
  opacity: available ? 1 : 0.3,
842
851
  }}
843
852
  disabled={!exists}
@@ -861,7 +870,7 @@
861
870
  <AddToCartButton
862
871
  disabled={!selectedVariant || !selectedVariant.availableForSale}
863
872
  onClick={() => {
864
- open('cart');
873
+ open("cart");
865
874
  }}
866
875
  lines={
867
876
  selectedVariant
@@ -875,7 +884,7 @@
875
884
  : []
876
885
  }
877
886
  >
878
- {selectedVariant?.availableForSale ? 'Add to cart' : 'Sold out'}
887
+ {selectedVariant?.availableForSale ? "Add to cart" : "Sold out"}
879
888
  </AddToCartButton>
880
889
  </div>
881
890
  );
@@ -898,7 +907,7 @@
898
907
  aria-label={name}
899
908
  className="product-option-label-swatch"
900
909
  style={{
901
- backgroundColor: color || 'transparent',
910
+ backgroundColor: color || "transparent",
902
911
  }}
903
912
  >
904
913
  {!!image && <img src={image} alt={name} />}
@@ -1399,21 +1408,21 @@
1399
1408
  New `withCache.fetch` is for caching simple fetch requests. This method caches the responses if they are OK responses, and you can pass `shouldCacheResponse`, `cacheKey`, etc. to modify behavior. `data` is the consumed body of the response (we need to consume to cache it).
1400
1409
 
1401
1410
  ```ts
1402
- const withCache = createWithCache({cache, waitUntil, request});
1411
+ const withCache = createWithCache({ cache, waitUntil, request });
1403
1412
 
1404
- const {data, response} = await withCache.fetch<{data: T; error: string}>(
1405
- 'my-cms.com/api',
1413
+ const { data, response } = await withCache.fetch<{ data: T; error: string }>(
1414
+ "my-cms.com/api",
1406
1415
  {
1407
- method: 'POST',
1408
- headers: {'Content-type': 'application/json'},
1416
+ method: "POST",
1417
+ headers: { "Content-type": "application/json" },
1409
1418
  body,
1410
1419
  },
1411
1420
  {
1412
1421
  cacheStrategy: CacheLong(),
1413
1422
  // Cache if there are no data errors or a specific data that make this result not suited for caching
1414
1423
  shouldCacheResponse: (result) => !result?.error,
1415
- cacheKey: ['my-cms', body],
1416
- displayName: 'My CMS query',
1424
+ cacheKey: ["my-cms", body],
1425
+ displayName: "My CMS query",
1417
1426
  },
1418
1427
  );
1419
1428
  ```
@@ -1989,9 +1998,9 @@
1989
1998
 
1990
1999
  ```tsx
1991
2000
  // app/lib/root-data.ts
1992
- import {useMatches} from '@remix-run/react';
1993
- import type {SerializeFrom} from '@shopify/remix-oxygen';
1994
- import type {loader} from '~/root';
2001
+ import { useMatches } from "@remix-run/react";
2002
+ import type { SerializeFrom } from "@shopify/remix-oxygen";
2003
+ import type { loader } from "~/root";
1995
2004
 
1996
2005
  /**
1997
2006
  * Access the result of the root loader from a React component.
@@ -2153,10 +2162,10 @@
2153
2162
  - This is an important fix to a bug with 404 routes and path-based i18n projects where some unknown routes would not properly render a 404. This fixes all new projects, but to fix existing projects, add a `($locale).tsx` route with the following contents: ([#1732](https://github.com/Shopify/hydrogen/pull/1732)) by [@blittle](https://github.com/blittle)
2154
2163
 
2155
2164
  ```ts
2156
- import {type LoaderFunctionArgs} from '@remix-run/server-runtime';
2165
+ import { type LoaderFunctionArgs } from "@remix-run/server-runtime";
2157
2166
 
2158
- export async function loader({params, context}: LoaderFunctionArgs) {
2159
- const {language, country} = context.storefront.i18n;
2167
+ export async function loader({ params, context }: LoaderFunctionArgs) {
2168
+ const { language, country } = context.storefront.i18n;
2160
2169
 
2161
2170
  if (
2162
2171
  params.locale &&
@@ -2164,7 +2173,7 @@
2164
2173
  ) {
2165
2174
  // If the locale URL param is defined, yet we still are still at the default locale
2166
2175
  // then the the locale param must be invalid, send to the 404 page
2167
- throw new Response(null, {status: 404});
2176
+ throw new Response(null, { status: 404 });
2168
2177
  }
2169
2178
 
2170
2179
  return null;
@@ -2220,11 +2229,11 @@
2220
2229
  ```yaml
2221
2230
  projects:
2222
2231
  default:
2223
- schema: 'node_modules/@shopify/hydrogen/storefront.schema.json'
2232
+ schema: "node_modules/@shopify/hydrogen/storefront.schema.json"
2224
2233
  documents:
2225
- - '!*.d.ts'
2226
- - '*.{ts,tsx,js,jsx}'
2227
- - 'app/**/*.{ts,tsx,js,jsx}'
2234
+ - "!*.d.ts"
2235
+ - "*.{ts,tsx,js,jsx}"
2236
+ - "app/**/*.{ts,tsx,js,jsx}"
2228
2237
  ```
2229
2238
 
2230
2239
  - Improve resiliency of `HydrogenSession` ([#1583](https://github.com/Shopify/hydrogen/pull/1583)) by [@blittle](https://github.com/blittle)
@@ -2439,8 +2448,8 @@
2439
2448
  ```ts
2440
2449
  // root.tsx
2441
2450
 
2442
- import {useMatches} from '@remix-run/react';
2443
- import {type SerializeFrom} from '@shopify/remix-oxygen';
2451
+ import { useMatches } from "@remix-run/react";
2452
+ import { type SerializeFrom } from "@shopify/remix-oxygen";
2444
2453
 
2445
2454
  export const useRootLoaderData = () => {
2446
2455
  const [root] = useMatches();
@@ -0,0 +1,14 @@
1
+ import {type LoaderFunctionArgs} from '@shopify/remix-oxygen';
2
+
3
+ export async function action({params, context, request}: LoaderFunctionArgs) {
4
+ const response = await fetch(
5
+ `https://${context.env.PUBLIC_CHECKOUT_DOMAIN}/api/${params.version}/graphql.json`,
6
+ {
7
+ method: 'POST',
8
+ body: request.body,
9
+ headers: request.headers,
10
+ },
11
+ );
12
+
13
+ return new Response(response.body, {headers: new Headers(response.headers)});
14
+ }
@@ -1,7 +1,12 @@
1
1
  import {type MetaFunction, useLoaderData} from '@remix-run/react';
2
2
  import type {CartQueryDataReturn} from '@shopify/hydrogen';
3
3
  import {CartForm} from '@shopify/hydrogen';
4
- import {data, type LoaderFunctionArgs, type ActionFunctionArgs, type HeadersFunction} from '@shopify/remix-oxygen';
4
+ import {
5
+ data,
6
+ type LoaderFunctionArgs,
7
+ type ActionFunctionArgs,
8
+ type HeadersFunction,
9
+ } from '@shopify/remix-oxygen';
5
10
  import {CartMain} from '~/components/CartMain';
6
11
 
7
12
  export const meta: MetaFunction = () => {
@@ -2,7 +2,7 @@
2
2
  "name": "skeleton",
3
3
  "private": true,
4
4
  "sideEffects": false,
5
- "version": "2025.4.0",
5
+ "version": "2025.4.1",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "build": "shopify hydrogen build --codegen",
@@ -17,7 +17,7 @@
17
17
  "@remix-run/react": "^2.16.1",
18
18
  "@remix-run/server-runtime": "^2.16.1",
19
19
  "graphql": "^16.10.0",
20
- "@shopify/hydrogen": "2025.4.0",
20
+ "@shopify/hydrogen": "2025.4.1",
21
21
  "@shopify/remix-oxygen": "^2.0.12",
22
22
  "graphql-tag": "^2.12.6",
23
23
  "isbot": "^5.1.22",
@@ -22,7 +22,8 @@ const ROUTE_MAP = {
22
22
  account: "account*",
23
23
  search: ["search", "api.predictive-search"],
24
24
  robots: "[robots.txt]",
25
- sitemap: ["[sitemap.xml]", "sitemap.$type.$page[.xml]"]
25
+ sitemap: ["[sitemap.xml]", "sitemap.$type.$page[.xml]"],
26
+ tokenlessApi: "api.$version.[graphql.json]"
26
27
  };
27
28
  let allRouteTemplateFiles = [];
28
29
  async function getResolvedRoutes(routeKeys = Object.keys(ROUTE_MAP)) {
@@ -880,7 +880,7 @@
880
880
  "aliases": [],
881
881
  "args": {
882
882
  "routeName": {
883
- "description": "The route to generate. One of home,page,cart,products,collections,policies,blogs,account,search,robots,sitemap,all.",
883
+ "description": "The route to generate. One of home,page,cart,products,collections,policies,blogs,account,search,robots,sitemap,tokenlessApi,all.",
884
884
  "name": "routeName",
885
885
  "options": [
886
886
  "home",
@@ -894,6 +894,7 @@
894
894
  "search",
895
895
  "robots",
896
896
  "sitemap",
897
+ "tokenlessApi",
897
898
  "all"
898
899
  ],
899
900
  "required": true
@@ -1748,5 +1749,5 @@
1748
1749
  ]
1749
1750
  }
1750
1751
  },
1751
- "version": "10.0.2"
1752
+ "version": "10.1.0"
1752
1753
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "@shopify:registry": "https://registry.npmjs.org"
6
6
  },
7
- "version": "10.0.2",
7
+ "version": "10.1.0",
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "repository": {