@shopify/cli-hydrogen 3.27.0 → 4.0.0-alpha.1

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.
Files changed (249) hide show
  1. package/dist/commands/hydrogen/build.js +89 -0
  2. package/dist/commands/hydrogen/dev.js +116 -0
  3. package/dist/commands/hydrogen/init.js +42 -0
  4. package/dist/commands/hydrogen/preview.js +34 -0
  5. package/dist/hooks/init.js +21 -0
  6. package/dist/templates/demo-store/.editorconfig +8 -0
  7. package/dist/templates/demo-store/.eslintignore +4 -0
  8. package/dist/templates/demo-store/.eslintrc.js +16 -0
  9. package/dist/templates/demo-store/.graphqlrc.yml +1 -0
  10. package/dist/templates/demo-store/.prettierignore +2 -0
  11. package/dist/templates/demo-store/.turbo/turbo-build.log +13 -0
  12. package/dist/templates/demo-store/app/components/AccountAddressBook.tsx +97 -0
  13. package/dist/templates/demo-store/app/components/AccountDetails.tsx +41 -0
  14. package/dist/templates/demo-store/app/components/AddToCartButton.tsx +42 -0
  15. package/dist/templates/demo-store/app/components/Breadcrumbs.tsx +36 -0
  16. package/dist/templates/demo-store/app/components/Button.tsx +56 -0
  17. package/dist/templates/demo-store/app/components/Cart.tsx +431 -0
  18. package/dist/templates/demo-store/app/components/CartLoading.tsx +50 -0
  19. package/dist/templates/demo-store/app/components/CountrySelector.tsx +180 -0
  20. package/dist/templates/demo-store/app/components/Drawer.tsx +115 -0
  21. package/dist/templates/demo-store/app/components/FeaturedCollections.tsx +54 -0
  22. package/dist/templates/demo-store/app/components/FeaturedProducts.tsx +116 -0
  23. package/dist/templates/demo-store/app/components/FeaturedSection.tsx +39 -0
  24. package/dist/templates/demo-store/app/components/GenericError.tsx +58 -0
  25. package/dist/templates/demo-store/app/components/Grid.tsx +44 -0
  26. package/dist/templates/demo-store/app/components/Hero.tsx +136 -0
  27. package/dist/templates/demo-store/app/components/Icon.tsx +253 -0
  28. package/dist/templates/demo-store/app/components/Input.tsx +24 -0
  29. package/dist/templates/demo-store/app/components/Layout.tsx +492 -0
  30. package/dist/templates/demo-store/app/components/Link.tsx +46 -0
  31. package/dist/templates/demo-store/app/components/Modal.tsx +46 -0
  32. package/dist/templates/demo-store/app/components/NotFound.tsx +22 -0
  33. package/dist/templates/demo-store/app/components/OrderCard.tsx +85 -0
  34. package/dist/templates/demo-store/app/components/Pagination.tsx +277 -0
  35. package/dist/templates/demo-store/app/components/ProductCard.tsx +146 -0
  36. package/dist/templates/demo-store/app/components/ProductGallery.tsx +114 -0
  37. package/dist/templates/demo-store/app/components/ProductGrid.tsx +93 -0
  38. package/dist/templates/demo-store/app/components/ProductSwimlane.tsx +30 -0
  39. package/dist/templates/demo-store/app/components/Skeleton.tsx +24 -0
  40. package/dist/templates/demo-store/app/components/SortFilter.tsx +411 -0
  41. package/dist/templates/demo-store/app/components/Text.tsx +192 -0
  42. package/dist/templates/demo-store/app/components/index.ts +28 -0
  43. package/dist/templates/demo-store/app/data/countries.ts +194 -0
  44. package/dist/templates/demo-store/app/data/index.ts +1037 -0
  45. package/dist/templates/demo-store/app/entry.client.tsx +4 -0
  46. package/dist/templates/demo-store/app/entry.server.tsx +26 -0
  47. package/dist/templates/demo-store/app/hooks/useCartFetchers.tsx +14 -0
  48. package/dist/templates/demo-store/app/hooks/useIsHydrated.tsx +12 -0
  49. package/dist/templates/demo-store/app/lib/const.ts +10 -0
  50. package/dist/templates/demo-store/app/lib/placeholders.ts +242 -0
  51. package/dist/templates/demo-store/app/lib/seo/common.tsx +324 -0
  52. package/dist/templates/demo-store/app/lib/seo/debugger.tsx +175 -0
  53. package/dist/templates/demo-store/app/lib/seo/image.tsx +32 -0
  54. package/dist/templates/demo-store/app/lib/seo/index.ts +4 -0
  55. package/dist/templates/demo-store/app/lib/seo/seo.tsx +24 -0
  56. package/dist/templates/demo-store/app/lib/seo/types.ts +70 -0
  57. package/dist/templates/demo-store/app/lib/session.server.ts +57 -0
  58. package/dist/templates/demo-store/app/lib/type.ts +21 -0
  59. package/dist/templates/demo-store/app/lib/utils.ts +310 -0
  60. package/dist/templates/demo-store/app/root.tsx +282 -0
  61. package/dist/templates/demo-store/app/routes/$.tsx +7 -0
  62. package/dist/templates/demo-store/app/routes/$lang/$.tsx +1 -0
  63. package/dist/templates/demo-store/app/routes/$lang/[robots.txt].tsx +1 -0
  64. package/dist/templates/demo-store/app/routes/$lang/[sitemap.xml].tsx +1 -0
  65. package/dist/templates/demo-store/app/routes/$lang/account/__private/address/$id.tsx +1 -0
  66. package/dist/templates/demo-store/app/routes/$lang/account/__private/edit.tsx +1 -0
  67. package/dist/templates/demo-store/app/routes/$lang/account/__private/logout.ts +1 -0
  68. package/dist/templates/demo-store/app/routes/$lang/account/__private/orders.$id.tsx +1 -0
  69. package/dist/templates/demo-store/app/routes/$lang/account/__public/activate.$id.$activationToken.tsx +6 -0
  70. package/dist/templates/demo-store/app/routes/$lang/account/__public/login.tsx +7 -0
  71. package/dist/templates/demo-store/app/routes/$lang/account/__public/recover.tsx +1 -0
  72. package/dist/templates/demo-store/app/routes/$lang/account/__public/register.tsx +6 -0
  73. package/dist/templates/demo-store/app/routes/$lang/account/__public/reset.$id.$resetToken.tsx +5 -0
  74. package/dist/templates/demo-store/app/routes/$lang/account.tsx +1 -0
  75. package/dist/templates/demo-store/app/routes/$lang/api/countries.tsx +1 -0
  76. package/dist/templates/demo-store/app/routes/$lang/api/products.tsx +1 -0
  77. package/dist/templates/demo-store/app/routes/$lang/cart.tsx +1 -0
  78. package/dist/templates/demo-store/app/routes/$lang/collections/$collectionHandle.tsx +6 -0
  79. package/dist/templates/demo-store/app/routes/$lang/collections/all.tsx +1 -0
  80. package/dist/templates/demo-store/app/routes/$lang/collections/index.tsx +1 -0
  81. package/dist/templates/demo-store/app/routes/$lang/featured-products.tsx +1 -0
  82. package/dist/templates/demo-store/app/routes/$lang/index.tsx +7 -0
  83. package/dist/templates/demo-store/app/routes/$lang/journal/$journalHandle.tsx +7 -0
  84. package/dist/templates/demo-store/app/routes/$lang/journal/index.tsx +1 -0
  85. package/dist/templates/demo-store/app/routes/$lang/og-image.tsx +1 -0
  86. package/dist/templates/demo-store/app/routes/$lang/pages/$pageHandle.tsx +1 -0
  87. package/dist/templates/demo-store/app/routes/$lang/policies/$policyHandle.tsx +1 -0
  88. package/dist/templates/demo-store/app/routes/$lang/policies/index.tsx +1 -0
  89. package/dist/templates/demo-store/app/routes/$lang/products/$productHandle.tsx +6 -0
  90. package/dist/templates/demo-store/app/routes/$lang/products/index.tsx +1 -0
  91. package/dist/templates/demo-store/app/routes/$lang/search.tsx +6 -0
  92. package/dist/templates/demo-store/app/routes/[robots.txt].tsx +40 -0
  93. package/dist/templates/demo-store/app/routes/[sitemap.xml].tsx +198 -0
  94. package/dist/templates/demo-store/app/routes/account/__private/address/$id.tsx +320 -0
  95. package/dist/templates/demo-store/app/routes/account/__private/edit.tsx +273 -0
  96. package/dist/templates/demo-store/app/routes/account/__private/logout.ts +29 -0
  97. package/dist/templates/demo-store/app/routes/account/__private/orders.$id.tsx +324 -0
  98. package/dist/templates/demo-store/app/routes/account/__public/activate.$id.$activationToken.tsx +218 -0
  99. package/dist/templates/demo-store/app/routes/account/__public/login.tsx +197 -0
  100. package/dist/templates/demo-store/app/routes/account/__public/recover.tsx +144 -0
  101. package/dist/templates/demo-store/app/routes/account/__public/register.tsx +184 -0
  102. package/dist/templates/demo-store/app/routes/account/__public/reset.$id.$resetToken.tsx +214 -0
  103. package/dist/templates/demo-store/app/routes/account.tsx +191 -0
  104. package/dist/templates/demo-store/app/routes/api/countries.tsx +22 -0
  105. package/dist/templates/demo-store/app/routes/api/products.tsx +116 -0
  106. package/dist/templates/demo-store/app/routes/cart.tsx +498 -0
  107. package/dist/templates/demo-store/app/routes/collections/$collectionHandle.tsx +308 -0
  108. package/dist/templates/demo-store/app/routes/collections/all.tsx +5 -0
  109. package/dist/templates/demo-store/app/routes/collections/index.tsx +195 -0
  110. package/dist/templates/demo-store/app/routes/discounts.$code.tsx +60 -0
  111. package/dist/templates/demo-store/app/routes/featured-products.tsx +58 -0
  112. package/dist/templates/demo-store/app/routes/index.tsx +254 -0
  113. package/dist/templates/demo-store/app/routes/journal/$journalHandle.tsx +147 -0
  114. package/dist/templates/demo-store/app/routes/journal/index.tsx +150 -0
  115. package/dist/templates/demo-store/app/routes/og-image.tsx +19 -0
  116. package/dist/templates/demo-store/app/routes/pages/$pageHandle.tsx +82 -0
  117. package/dist/templates/demo-store/app/routes/policies/$policyHandle.tsx +117 -0
  118. package/dist/templates/demo-store/app/routes/policies/index.tsx +104 -0
  119. package/dist/templates/demo-store/app/routes/products/$productHandle.tsx +561 -0
  120. package/dist/templates/demo-store/app/routes/products/index.tsx +155 -0
  121. package/dist/templates/demo-store/app/routes/search.tsx +205 -0
  122. package/dist/templates/demo-store/app/styles/custom-font.css +13 -0
  123. package/dist/templates/demo-store/package-lock.json +25515 -0
  124. package/dist/templates/demo-store/package.json +67 -0
  125. package/dist/templates/demo-store/playwright.config.ts +109 -0
  126. package/dist/templates/demo-store/postcss.config.js +10 -0
  127. package/dist/templates/demo-store/public/favicon.svg +28 -0
  128. package/dist/templates/demo-store/public/fonts/IBMPlexSerif-Text.woff2 +0 -0
  129. package/dist/templates/demo-store/public/fonts/IBMPlexSerif-TextItalic.woff2 +0 -0
  130. package/dist/templates/demo-store/remix.config.js +12 -0
  131. package/dist/templates/demo-store/remix.env.d.ts +34 -0
  132. package/dist/templates/demo-store/remix.init/index.ts +15 -0
  133. package/dist/templates/demo-store/remix.init/package.json +7 -0
  134. package/dist/templates/demo-store/server.ts +87 -0
  135. package/dist/templates/demo-store/styles/app.css +182 -0
  136. package/dist/templates/demo-store/tailwind.config.js +70 -0
  137. package/dist/templates/demo-store/tests/cart.test.ts +70 -0
  138. package/dist/templates/demo-store/tests/seo.test.ts +36 -0
  139. package/dist/templates/demo-store/tests/utils.ts +100 -0
  140. package/dist/templates/demo-store/tsconfig.json +26 -0
  141. package/dist/templates/hello-world/.eslintignore +4 -0
  142. package/dist/templates/hello-world/.eslintrc.js +6 -0
  143. package/dist/templates/hello-world/.graphqlrc.yml +1 -0
  144. package/dist/templates/hello-world/.turbo/turbo-build.log +9 -0
  145. package/dist/templates/hello-world/README.md +20 -0
  146. package/dist/templates/hello-world/app/components/Layout.tsx +15 -0
  147. package/dist/templates/hello-world/app/components/index.ts +1 -0
  148. package/dist/templates/hello-world/app/entry.client.tsx +4 -0
  149. package/dist/templates/hello-world/app/entry.server.tsx +21 -0
  150. package/dist/templates/hello-world/app/root.tsx +212 -0
  151. package/dist/templates/hello-world/app/routes/index.tsx +7 -0
  152. package/dist/templates/hello-world/app/styles/app.css +38 -0
  153. package/dist/templates/hello-world/package-lock.json +27641 -0
  154. package/dist/templates/hello-world/package.json +41 -0
  155. package/dist/templates/hello-world/public/favicon.svg +28 -0
  156. package/dist/templates/hello-world/remix.env.d.ts +29 -0
  157. package/dist/templates/hello-world/server.ts +127 -0
  158. package/dist/templates/hello-world/tsconfig.json +25 -0
  159. package/dist/utils/config.js +81 -0
  160. package/dist/utils/flags.js +15 -0
  161. package/dist/utils/log.js +20 -0
  162. package/dist/utils/mini-oxygen.js +70 -0
  163. package/package.json +27 -64
  164. package/tmp-create-app.mjs +29 -0
  165. package/LICENSE +0 -8
  166. package/README.md +0 -63
  167. package/dist/cli/commands/hydrogen/add/eslint.d.ts +0 -11
  168. package/dist/cli/commands/hydrogen/add/eslint.js +0 -26
  169. package/dist/cli/commands/hydrogen/add/eslint.js.map +0 -1
  170. package/dist/cli/commands/hydrogen/add/tailwind.d.ts +0 -11
  171. package/dist/cli/commands/hydrogen/add/tailwind.js +0 -26
  172. package/dist/cli/commands/hydrogen/add/tailwind.js.map +0 -1
  173. package/dist/cli/commands/hydrogen/build.d.ts +0 -14
  174. package/dist/cli/commands/hydrogen/build.js +0 -49
  175. package/dist/cli/commands/hydrogen/build.js.map +0 -1
  176. package/dist/cli/commands/hydrogen/deploy.d.ts +0 -19
  177. package/dist/cli/commands/hydrogen/deploy.js +0 -58
  178. package/dist/cli/commands/hydrogen/deploy.js.map +0 -1
  179. package/dist/cli/commands/hydrogen/dev.d.ts +0 -13
  180. package/dist/cli/commands/hydrogen/dev.js +0 -31
  181. package/dist/cli/commands/hydrogen/dev.js.map +0 -1
  182. package/dist/cli/commands/hydrogen/info.d.ts +0 -12
  183. package/dist/cli/commands/hydrogen/info.js +0 -28
  184. package/dist/cli/commands/hydrogen/info.js.map +0 -1
  185. package/dist/cli/commands/hydrogen/preview.d.ts +0 -13
  186. package/dist/cli/commands/hydrogen/preview.js +0 -46
  187. package/dist/cli/commands/hydrogen/preview.js.map +0 -1
  188. package/dist/cli/constants.d.ts +0 -15
  189. package/dist/cli/constants.js +0 -16
  190. package/dist/cli/constants.js.map +0 -1
  191. package/dist/cli/flags.d.ts +0 -4
  192. package/dist/cli/flags.js +0 -16
  193. package/dist/cli/flags.js.map +0 -1
  194. package/dist/cli/models/hydrogen.d.ts +0 -22
  195. package/dist/cli/models/hydrogen.js +0 -82
  196. package/dist/cli/models/hydrogen.js.map +0 -1
  197. package/dist/cli/prompts/git-init.d.ts +0 -1
  198. package/dist/cli/prompts/git-init.js +0 -16
  199. package/dist/cli/prompts/git-init.js.map +0 -1
  200. package/dist/cli/services/build/check-lockfile.d.ts +0 -3
  201. package/dist/cli/services/build/check-lockfile.js +0 -80
  202. package/dist/cli/services/build/check-lockfile.js.map +0 -1
  203. package/dist/cli/services/build.d.ts +0 -14
  204. package/dist/cli/services/build.js +0 -44
  205. package/dist/cli/services/build.js.map +0 -1
  206. package/dist/cli/services/deploy/config.d.ts +0 -4
  207. package/dist/cli/services/deploy/config.js +0 -49
  208. package/dist/cli/services/deploy/config.js.map +0 -1
  209. package/dist/cli/services/deploy/error.d.ts +0 -4
  210. package/dist/cli/services/deploy/error.js +0 -11
  211. package/dist/cli/services/deploy/error.js.map +0 -1
  212. package/dist/cli/services/deploy/graphql/create_deployment.d.ts +0 -10
  213. package/dist/cli/services/deploy/graphql/create_deployment.js +0 -15
  214. package/dist/cli/services/deploy/graphql/create_deployment.js.map +0 -1
  215. package/dist/cli/services/deploy/graphql/upload_deployment.d.ts +0 -1
  216. package/dist/cli/services/deploy/graphql/upload_deployment.js +0 -16
  217. package/dist/cli/services/deploy/graphql/upload_deployment.js.map +0 -1
  218. package/dist/cli/services/deploy/types.d.ts +0 -37
  219. package/dist/cli/services/deploy/types.js +0 -2
  220. package/dist/cli/services/deploy/types.js.map +0 -1
  221. package/dist/cli/services/deploy/upload.d.ts +0 -5
  222. package/dist/cli/services/deploy/upload.js +0 -81
  223. package/dist/cli/services/deploy/upload.js.map +0 -1
  224. package/dist/cli/services/deploy.d.ts +0 -2
  225. package/dist/cli/services/deploy.js +0 -103
  226. package/dist/cli/services/deploy.js.map +0 -1
  227. package/dist/cli/services/dev/check-version.d.ts +0 -1
  228. package/dist/cli/services/dev/check-version.js +0 -30
  229. package/dist/cli/services/dev/check-version.js.map +0 -1
  230. package/dist/cli/services/dev.d.ts +0 -10
  231. package/dist/cli/services/dev.js +0 -36
  232. package/dist/cli/services/dev.js.map +0 -1
  233. package/dist/cli/services/eslint.d.ts +0 -8
  234. package/dist/cli/services/eslint.js +0 -74
  235. package/dist/cli/services/eslint.js.map +0 -1
  236. package/dist/cli/services/info.d.ts +0 -7
  237. package/dist/cli/services/info.js +0 -131
  238. package/dist/cli/services/info.js.map +0 -1
  239. package/dist/cli/services/preview.d.ts +0 -12
  240. package/dist/cli/services/preview.js +0 -63
  241. package/dist/cli/services/preview.js.map +0 -1
  242. package/dist/cli/services/tailwind.d.ts +0 -9
  243. package/dist/cli/services/tailwind.js +0 -103
  244. package/dist/cli/services/tailwind.js.map +0 -1
  245. package/dist/cli/utilities/load-config.d.ts +0 -5
  246. package/dist/cli/utilities/load-config.js +0 -6
  247. package/dist/cli/utilities/load-config.js.map +0 -1
  248. package/dist/tsconfig.tsbuildinfo +0 -1
  249. package/oclif.manifest.json +0 -1
@@ -0,0 +1,282 @@
1
+ import {
2
+ defer,
3
+ type LinksFunction,
4
+ type MetaFunction,
5
+ type LoaderArgs,
6
+ type AppLoadContext,
7
+ } from '@shopify/remix-oxygen';
8
+ import {
9
+ Links,
10
+ Meta,
11
+ Outlet,
12
+ Scripts,
13
+ ScrollRestoration,
14
+ useCatch,
15
+ useLoaderData,
16
+ useMatches,
17
+ } from '@remix-run/react';
18
+ import {Layout} from '~/components';
19
+ import {getLayoutData, type LayoutData} from '~/data';
20
+ import {GenericError} from './components/GenericError';
21
+ import {NotFound} from './components/NotFound';
22
+ import {Seo, Debugger} from './lib/seo';
23
+
24
+ import styles from './styles/app.css';
25
+ import favicon from '../public/favicon.svg';
26
+ import {DEFAULT_LOCALE, getLocaleFromRequest} from './lib/utils';
27
+ import invariant from 'tiny-invariant';
28
+ import {Cart} from '@shopify/hydrogen-react/storefront-api-types';
29
+
30
+ export const handle = {
31
+ // @todo - remove any and type the seo callback
32
+ seo: (data: any) => ({
33
+ title: data?.layout?.shop?.name,
34
+ bypassTitleTemplate: true,
35
+ titleTemplate: `%s | ${data?.layout?.shop?.name}`,
36
+ }),
37
+ };
38
+
39
+ export const links: LinksFunction = () => {
40
+ return [
41
+ {rel: 'stylesheet', href: styles},
42
+ {
43
+ rel: 'preconnect',
44
+ href: 'https://cdn.shopify.com',
45
+ },
46
+ {
47
+ rel: 'preconnect',
48
+ href: 'https://shop.app',
49
+ },
50
+ {rel: 'icon', type: 'image/svg+xml', href: favicon},
51
+ ];
52
+ };
53
+
54
+ export const meta: MetaFunction = () => ({
55
+ charset: 'utf-8',
56
+ viewport: 'width=device-width,initial-scale=1',
57
+ });
58
+
59
+ export async function loader({context, request}: LoaderArgs) {
60
+ const [cartId, layout, selectedLocale] = await Promise.all([
61
+ context.session.get('cartId'),
62
+ getLayoutData(context),
63
+ getLocaleFromRequest(request),
64
+ ]);
65
+
66
+ return defer({
67
+ layout,
68
+ selectedLocale,
69
+ cart: cartId ? getCart(context, cartId) : undefined,
70
+ });
71
+ }
72
+
73
+ export default function App() {
74
+ const data = useLoaderData<typeof loader>();
75
+ const locale = data.selectedLocale ?? DEFAULT_LOCALE;
76
+
77
+ return (
78
+ <html lang={locale.language}>
79
+ <head>
80
+ <Seo />
81
+ <Meta />
82
+ <Links />
83
+ </head>
84
+ <body>
85
+ <Layout
86
+ layout={data.layout as LayoutData}
87
+ key={`${locale.language}-${locale.country}`}
88
+ >
89
+ <Outlet />
90
+ </Layout>
91
+ <Debugger />
92
+ <ScrollRestoration />
93
+ <Scripts />
94
+ </body>
95
+ </html>
96
+ );
97
+ }
98
+
99
+ export function CatchBoundary() {
100
+ const [root] = useMatches();
101
+ const caught = useCatch();
102
+ const isNotFound = caught.status === 404;
103
+ const locale = root.data?.selectedLocale ?? DEFAULT_LOCALE;
104
+
105
+ return (
106
+ <html lang={locale.language}>
107
+ <head>
108
+ <title>{isNotFound ? 'Not found' : 'Error'}</title>
109
+ <Meta />
110
+ <Links />
111
+ </head>
112
+ <body>
113
+ <Layout
114
+ layout={root?.data?.layout}
115
+ key={`${locale.language}-${locale.country}`}
116
+ >
117
+ {isNotFound ? (
118
+ <NotFound type={caught.data?.pageType} />
119
+ ) : (
120
+ <GenericError
121
+ error={{message: `${caught.status} ${caught.data}`}}
122
+ />
123
+ )}
124
+ </Layout>
125
+ <Scripts />
126
+ </body>
127
+ </html>
128
+ );
129
+ }
130
+
131
+ export function ErrorBoundary({error}: {error: Error}) {
132
+ const [root] = useMatches();
133
+ const locale = root?.data?.selectedLocale ?? DEFAULT_LOCALE;
134
+
135
+ return (
136
+ <html lang={locale.language}>
137
+ <head>
138
+ <title>Error</title>
139
+ <Meta />
140
+ <Links />
141
+ </head>
142
+ <body>
143
+ <Layout layout={root?.data?.layout}>
144
+ <GenericError error={error} />
145
+ </Layout>
146
+ <Scripts />
147
+ <Debugger />
148
+ </body>
149
+ </html>
150
+ );
151
+ }
152
+
153
+ const CART_QUERY = `#graphql
154
+ query CartQuery($cartId: ID!, $country: CountryCode, $language: LanguageCode)
155
+ @inContext(country: $country, language: $language) {
156
+ cart(id: $cartId) {
157
+ ...CartFragment
158
+ }
159
+ }
160
+
161
+ fragment CartFragment on Cart {
162
+ id
163
+ checkoutUrl
164
+ totalQuantity
165
+ buyerIdentity {
166
+ countryCode
167
+ customer {
168
+ id
169
+ email
170
+ firstName
171
+ lastName
172
+ displayName
173
+ }
174
+ email
175
+ phone
176
+ }
177
+ lines(first: 100) {
178
+ edges {
179
+ node {
180
+ id
181
+ quantity
182
+ attributes {
183
+ key
184
+ value
185
+ }
186
+ cost {
187
+ totalAmount {
188
+ amount
189
+ currencyCode
190
+ }
191
+ amountPerQuantity {
192
+ amount
193
+ currencyCode
194
+ }
195
+ compareAtAmountPerQuantity {
196
+ amount
197
+ currencyCode
198
+ }
199
+ }
200
+ merchandise {
201
+ ... on ProductVariant {
202
+ id
203
+ availableForSale
204
+ compareAtPrice {
205
+ ...MoneyFragment
206
+ }
207
+ price {
208
+ ...MoneyFragment
209
+ }
210
+ requiresShipping
211
+ title
212
+ image {
213
+ ...ImageFragment
214
+ }
215
+ product {
216
+ handle
217
+ title
218
+ id
219
+ }
220
+ selectedOptions {
221
+ name
222
+ value
223
+ }
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ cost {
230
+ subtotalAmount {
231
+ ...MoneyFragment
232
+ }
233
+ totalAmount {
234
+ ...MoneyFragment
235
+ }
236
+ totalDutyAmount {
237
+ ...MoneyFragment
238
+ }
239
+ totalTaxAmount {
240
+ ...MoneyFragment
241
+ }
242
+ }
243
+ note
244
+ attributes {
245
+ key
246
+ value
247
+ }
248
+ discountCodes {
249
+ code
250
+ }
251
+ }
252
+
253
+ fragment MoneyFragment on MoneyV2 {
254
+ currencyCode
255
+ amount
256
+ }
257
+
258
+ fragment ImageFragment on Image {
259
+ id
260
+ url
261
+ altText
262
+ width
263
+ height
264
+ }
265
+ `;
266
+
267
+ export async function getCart({storefront}: AppLoadContext, cartId: string) {
268
+ invariant(storefront, 'missing storefront client in cart query');
269
+
270
+ const {cart} = await storefront.query<{cart: Cart}>(CART_QUERY, {
271
+ variables: {
272
+ cartId,
273
+ country: storefront.i18n?.country,
274
+ language: storefront.i18n?.language,
275
+ },
276
+ cache: storefront.CacheNone(),
277
+ });
278
+
279
+ invariant(cart, 'No data returned from Shopify API');
280
+
281
+ return cart;
282
+ }
@@ -0,0 +1,7 @@
1
+ export async function loader() {
2
+ throw new Response('Not found', {status: 404});
3
+ }
4
+
5
+ export default function Component() {
6
+ return null;
7
+ }
@@ -0,0 +1 @@
1
+ export {default, loader} from '~/routes/$';
@@ -0,0 +1 @@
1
+ export {loader} from '~/routes/[robots.txt]';
@@ -0,0 +1 @@
1
+ export {loader} from '~/routes/[sitemap.xml]';
@@ -0,0 +1 @@
1
+ export {action, default, handle} from '~/routes/account/__private/address/$id';
@@ -0,0 +1 @@
1
+ export {action, default, handle} from '~/routes/account/__private/edit';
@@ -0,0 +1 @@
1
+ export {action, loader, logout} from '~/routes/account/__private/logout';
@@ -0,0 +1 @@
1
+ export {default, loader, meta} from '~/routes/account/__private/orders.$id';
@@ -0,0 +1,6 @@
1
+ export {
2
+ action,
3
+ default,
4
+ handle,
5
+ meta,
6
+ } from '~/routes/account/__public/activate.$id.$activationToken';
@@ -0,0 +1,7 @@
1
+ export {
2
+ action,
3
+ default,
4
+ handle,
5
+ loader,
6
+ meta,
7
+ } from '~/routes/account/__public/login';
@@ -0,0 +1 @@
1
+ export {action, default, loader, meta} from '~/routes/account/__public/recover';
@@ -0,0 +1,6 @@
1
+ export {
2
+ action,
3
+ default,
4
+ loader,
5
+ meta,
6
+ } from '~/routes/account/__public/register';
@@ -0,0 +1,5 @@
1
+ export {
2
+ action,
3
+ default,
4
+ meta,
5
+ } from '~/routes/account/__public/reset.$id.$resetToken';
@@ -0,0 +1 @@
1
+ export {default, loader} from '~/routes/account';
@@ -0,0 +1 @@
1
+ export {default, loader} from '~/routes/api/countries';
@@ -0,0 +1 @@
1
+ export {default, loader} from '~/routes/api/products';
@@ -0,0 +1 @@
1
+ export {default} from '~/routes/cart';
@@ -0,0 +1,6 @@
1
+ export {
2
+ default,
3
+ handle,
4
+ loader,
5
+ meta,
6
+ } from '~/routes/collections/$collectionHandle';
@@ -0,0 +1 @@
1
+ export {loader} from '~/routes/collections/all';
@@ -0,0 +1 @@
1
+ export {default, handle, loader, meta} from '~/routes/collections/index';
@@ -0,0 +1 @@
1
+ export {getFeaturedData, loader} from '~/routes/featured-products';
@@ -0,0 +1,7 @@
1
+ export {
2
+ FEATURED_COLLECTIONS_QUERY,
3
+ HOMEPAGE_FEATURED_PRODUCTS_QUERY,
4
+ default,
5
+ handle,
6
+ loader,
7
+ } from '~/routes/index';
@@ -0,0 +1,7 @@
1
+ export {
2
+ default,
3
+ handle,
4
+ links,
5
+ loader,
6
+ meta,
7
+ } from '~/routes/journal/$journalHandle';
@@ -0,0 +1 @@
1
+ export {default, handle, loader, meta} from '~/routes/journal/index';
@@ -0,0 +1 @@
1
+ export {loader} from '~/routes/og-image';
@@ -0,0 +1 @@
1
+ export {default, handle, loader, meta} from '~/routes/pages/$pageHandle';
@@ -0,0 +1 @@
1
+ export {default, loader, meta} from '~/routes/policies/$policyHandle';
@@ -0,0 +1 @@
1
+ export {default, handle, loader, meta} from '~/routes/policies/index';
@@ -0,0 +1,6 @@
1
+ export {
2
+ ProductForm,
3
+ default,
4
+ handle,
5
+ loader,
6
+ } from '~/routes/products/$productHandle';
@@ -0,0 +1 @@
1
+ export {default, handle, loader, meta} from '~/routes/products/index';
@@ -0,0 +1,6 @@
1
+ export {
2
+ default,
3
+ getNoResultRecommendations,
4
+ handle,
5
+ loader,
6
+ } from '~/routes/search';
@@ -0,0 +1,40 @@
1
+ import {type LoaderArgs} from '@shopify/remix-oxygen';
2
+
3
+ export const loader = ({request}: LoaderArgs) => {
4
+ const url = new URL(request.url);
5
+
6
+ return new Response(robotsTxtData({url: url.origin}), {
7
+ status: 200,
8
+ headers: {
9
+ 'content-type': 'text/plain',
10
+ // Cache for 24 hours
11
+ 'cache-control': `max-age=${60 * 60 * 24}`,
12
+ },
13
+ });
14
+ };
15
+
16
+ function robotsTxtData({url}: {url: string}) {
17
+ const sitemapUrl = url ? `${url}/sitemap.xml` : undefined;
18
+
19
+ return `
20
+ User-agent: *
21
+ Disallow: /admin
22
+ Disallow: /cart
23
+ Disallow: /orders
24
+ Disallow: /checkouts/
25
+ Disallow: /checkout
26
+ Disallow: /carts
27
+ Disallow: /account
28
+ ${sitemapUrl ? `Sitemap: ${sitemapUrl}` : ''}
29
+
30
+ # Google adsbot ignores robots.txt unless specifically named!
31
+ User-agent: adsbot-google
32
+ Disallow: /checkouts/
33
+ Disallow: /checkout
34
+ Disallow: /carts
35
+ Disallow: /orders
36
+
37
+ User-agent: Pinterest
38
+ Crawl-delay: 1
39
+ `.trim();
40
+ }
@@ -0,0 +1,198 @@
1
+ import {flattenConnection} from '@shopify/hydrogen-react';
2
+ import type {LoaderArgs} from '@shopify/remix-oxygen';
3
+ import {
4
+ CollectionConnection,
5
+ PageConnection,
6
+ ProductConnection,
7
+ } from '@shopify/hydrogen-react/storefront-api-types';
8
+ import invariant from 'tiny-invariant';
9
+
10
+ const MAX_URLS = 250; // the google limit is 50K, however, SF API only allow querying for 250 resources each time
11
+
12
+ interface SitemapQueryData {
13
+ products: ProductConnection;
14
+ collections: CollectionConnection;
15
+ pages: PageConnection;
16
+ }
17
+
18
+ interface ProductEntry {
19
+ url: string;
20
+ lastMod: string;
21
+ changeFreq: string;
22
+ image?: {
23
+ url: string;
24
+ title?: string;
25
+ caption?: string;
26
+ };
27
+ }
28
+
29
+ export async function loader({request, context: {storefront}}: LoaderArgs) {
30
+ const data = await storefront.query<SitemapQueryData>(SITEMAP_QUERY, {
31
+ variables: {
32
+ urlLimits: MAX_URLS,
33
+ language: storefront.i18n?.language,
34
+ },
35
+ });
36
+
37
+ invariant(data, 'Sitemap data is missing');
38
+
39
+ return new Response(
40
+ shopSitemap({data, baseUrl: new URL(request.url).origin}),
41
+ {
42
+ headers: {
43
+ 'content-type': 'application/xml',
44
+ // Cache for 24 hours
45
+ 'cache-control': `max-age=${60 * 60 * 24}`,
46
+ },
47
+ },
48
+ );
49
+ }
50
+
51
+ function shopSitemap({
52
+ data,
53
+ baseUrl,
54
+ }: {
55
+ data: SitemapQueryData;
56
+ baseUrl: string;
57
+ }) {
58
+ const productsData = flattenConnection(data.products)
59
+ .filter((product) => product.onlineStoreUrl)
60
+ .map((product) => {
61
+ const url = `${baseUrl}/products/${product.handle}`;
62
+
63
+ const finalObject: ProductEntry = {
64
+ url,
65
+ lastMod: product.updatedAt!,
66
+ changeFreq: 'daily',
67
+ };
68
+
69
+ if (product.featuredImage?.url) {
70
+ finalObject.image = {
71
+ url: product.featuredImage!.url,
72
+ };
73
+
74
+ if (product.title) {
75
+ finalObject.image.title = product.title;
76
+ }
77
+
78
+ if (product.featuredImage!.altText) {
79
+ finalObject.image.caption = product.featuredImage!.altText;
80
+ }
81
+ }
82
+
83
+ return finalObject;
84
+ });
85
+
86
+ const collectionsData = flattenConnection(data.collections)
87
+ .filter((collection) => collection.onlineStoreUrl)
88
+ .map((collection) => {
89
+ const url = `${baseUrl}/collections/${collection.handle}`;
90
+
91
+ return {
92
+ url,
93
+ lastMod: collection.updatedAt,
94
+ changeFreq: 'daily',
95
+ };
96
+ });
97
+
98
+ const pagesData = flattenConnection(data.pages)
99
+ .filter((page) => page.onlineStoreUrl)
100
+ .map((page) => {
101
+ const url = `${baseUrl}/pages/${page.handle}`;
102
+
103
+ return {
104
+ url,
105
+ lastMod: page.updatedAt,
106
+ changeFreq: 'weekly',
107
+ };
108
+ });
109
+
110
+ const urlsDatas = [...productsData, ...collectionsData, ...pagesData];
111
+
112
+ return `
113
+ <urlset
114
+ xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
115
+ xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
116
+ >
117
+ ${urlsDatas.map((url) => renderUrlTag(url!)).join('')}
118
+ </urlset>`;
119
+ }
120
+
121
+ function renderUrlTag({
122
+ url,
123
+ lastMod,
124
+ changeFreq,
125
+ image,
126
+ }: {
127
+ url: string;
128
+ lastMod?: string;
129
+ changeFreq?: string;
130
+ image?: {
131
+ url: string;
132
+ title?: string;
133
+ caption?: string;
134
+ };
135
+ }) {
136
+ return `
137
+ <url>
138
+ <loc>${url}</loc>
139
+ <lastmod>${lastMod}</lastmod>
140
+ <changefreq>${changeFreq}</changefreq>
141
+ ${
142
+ image
143
+ ? `
144
+ <image:image>
145
+ <image:loc>${image.url}</image:loc>
146
+ <image:title>${image.title ?? ''}</image:title>
147
+ <image:caption>${image.caption ?? ''}</image:caption>
148
+ </image:image>`
149
+ : ''
150
+ }
151
+
152
+ </url>
153
+ `;
154
+ }
155
+
156
+ const SITEMAP_QUERY = `#graphql
157
+ query sitemaps($urlLimits: Int, $language: LanguageCode)
158
+ @inContext(language: $language) {
159
+ products(
160
+ first: $urlLimits
161
+ query: "published_status:'online_store:visible'"
162
+ ) {
163
+ edges {
164
+ node {
165
+ updatedAt
166
+ handle
167
+ onlineStoreUrl
168
+ title
169
+ featuredImage {
170
+ url
171
+ altText
172
+ }
173
+ }
174
+ }
175
+ }
176
+ collections(
177
+ first: $urlLimits
178
+ query: "published_status:'online_store:visible'"
179
+ ) {
180
+ edges {
181
+ node {
182
+ updatedAt
183
+ handle
184
+ onlineStoreUrl
185
+ }
186
+ }
187
+ }
188
+ pages(first: $urlLimits, query: "published_status:'published'") {
189
+ edges {
190
+ node {
191
+ updatedAt
192
+ handle
193
+ onlineStoreUrl
194
+ }
195
+ }
196
+ }
197
+ }
198
+ `;