@doswiftly/cli 0.1.18 → 0.1.20

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 (277) hide show
  1. package/README.md +23 -323
  2. package/dist/commands/check.js +1 -1
  3. package/dist/commands/check.js.map +1 -1
  4. package/dist/commands/deploy.d.ts +20 -0
  5. package/dist/commands/deploy.d.ts.map +1 -1
  6. package/dist/commands/deploy.js +249 -17
  7. package/dist/commands/deploy.js.map +1 -1
  8. package/dist/commands/doctor.js +3 -3
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/init.js +4 -4
  11. package/dist/commands/sdk.js +5 -5
  12. package/dist/commands/sdk.js.map +1 -1
  13. package/dist/commands/template.js +4 -4
  14. package/dist/commands/template.js.map +1 -1
  15. package/dist/commands/types.js +5 -5
  16. package/dist/commands/types.js.map +1 -1
  17. package/dist/commands/verify.js +2 -2
  18. package/dist/commands/verify.js.map +1 -1
  19. package/dist/lib/package-manager.d.ts +1 -1
  20. package/dist/lib/package-manager.js +1 -1
  21. package/package.json +4 -4
  22. package/templates/storefront-minimal/.github/workflows/build-template.yml +10 -0
  23. package/templates/storefront-minimal/wrangler.toml +11 -0
  24. package/templates/storefront-nextjs/.github/workflows/build-template.yml +10 -0
  25. package/templates/storefront-nextjs/README.md +16 -12
  26. package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
  27. package/templates/storefront-nextjs/app/account/page.tsx +2 -2
  28. package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
  29. package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
  30. package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
  31. package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
  32. package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
  33. package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
  34. package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
  35. package/templates/storefront-nextjs/app/page.tsx +1 -1
  36. package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
  37. package/templates/storefront-nextjs/app/products/page.tsx +2 -2
  38. package/templates/storefront-nextjs/app/search/page.tsx +1 -1
  39. package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
  40. package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
  41. package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
  42. package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
  43. package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
  44. package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
  45. package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
  46. package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
  47. package/templates/storefront-nextjs/components/providers.tsx +1 -1
  48. package/templates/storefront-nextjs/lib/currency.tsx +3 -3
  49. package/templates/storefront-nextjs/lib/format.ts +1 -1
  50. package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
  51. package/templates/storefront-nextjs/package.dev.json +1 -1
  52. package/templates/storefront-nextjs/package.json +1 -1
  53. package/templates/storefront-nextjs/package.json.template +1 -1
  54. package/templates/storefront-nextjs/wrangler.toml +11 -0
  55. package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +10 -0
  56. package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
  57. package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
  58. package/templates/storefront-nextjs-shadcn/CLAUDE.md +172 -35
  59. package/templates/storefront-nextjs-shadcn/README.md +29 -162
  60. package/templates/storefront-nextjs-shadcn/app/{about → [locale]/about}/page.tsx +17 -14
  61. package/templates/storefront-nextjs-shadcn/app/[locale]/account/addresses/page.tsx +226 -0
  62. package/templates/storefront-nextjs-shadcn/app/[locale]/account/error.tsx +46 -0
  63. package/templates/storefront-nextjs-shadcn/app/[locale]/account/loading.tsx +19 -0
  64. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loyalty/page.tsx +89 -193
  65. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/loading.tsx +60 -0
  66. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/page.tsx +119 -0
  67. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/tracking/page.tsx +27 -25
  68. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/page.tsx +101 -0
  69. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/page.tsx +9 -7
  70. package/templates/storefront-nextjs-shadcn/app/[locale]/account/settings/page.tsx +208 -0
  71. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx +24 -17
  72. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/login/page.tsx +5 -2
  73. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/register/page.tsx +5 -2
  74. package/templates/storefront-nextjs-shadcn/app/[locale]/blog/[slug]/loading.tsx +17 -0
  75. package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/page.tsx +44 -3
  76. package/templates/storefront-nextjs-shadcn/app/[locale]/blog/loading.tsx +19 -0
  77. package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/page.tsx +2 -1
  78. package/templates/storefront-nextjs-shadcn/app/[locale]/cart/loading.tsx +26 -0
  79. package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/page.tsx +20 -13
  80. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/category-products-client.tsx +58 -0
  81. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/loading.tsx +32 -0
  82. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/page.tsx +95 -0
  83. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/page.tsx +21 -12
  84. package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/error.tsx +43 -0
  85. package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/loading.tsx +31 -0
  86. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/page.tsx +334 -253
  87. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/success/[orderId]/page.tsx +36 -34
  88. package/templates/storefront-nextjs-shadcn/app/[locale]/collections/[handle]/loading.tsx +19 -0
  89. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/page.tsx +6 -4
  90. package/templates/storefront-nextjs-shadcn/app/[locale]/collections/loading.tsx +18 -0
  91. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/page.tsx +20 -12
  92. package/templates/storefront-nextjs-shadcn/app/{contact → [locale]/contact}/page.tsx +24 -21
  93. package/templates/storefront-nextjs-shadcn/app/{error.tsx → [locale]/error.tsx} +13 -8
  94. package/templates/storefront-nextjs-shadcn/app/[locale]/layout.tsx +92 -0
  95. package/templates/storefront-nextjs-shadcn/app/{not-found.tsx → [locale]/not-found.tsx} +13 -18
  96. package/templates/storefront-nextjs-shadcn/app/{page.tsx → [locale]/page.tsx} +8 -4
  97. package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/error.tsx +43 -0
  98. package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/loading.tsx +29 -0
  99. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/page.tsx +17 -14
  100. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/product-client.tsx +18 -62
  101. package/templates/storefront-nextjs-shadcn/app/[locale]/products/loading.tsx +32 -0
  102. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/page.tsx +6 -3
  103. package/templates/storefront-nextjs-shadcn/app/[locale]/products/products-client.tsx +450 -0
  104. package/templates/storefront-nextjs-shadcn/app/[locale]/search/loading.tsx +18 -0
  105. package/templates/storefront-nextjs-shadcn/app/{wishlist → [locale]/wishlist}/page.tsx +27 -28
  106. package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
  107. package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
  108. package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
  109. package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
  110. package/templates/storefront-nextjs-shadcn/app/layout.tsx +8 -35
  111. package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
  112. package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +25 -20
  113. package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +11 -10
  114. package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
  115. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +17 -13
  116. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +42 -30
  117. package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
  118. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +18 -16
  119. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +37 -58
  120. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +85 -66
  121. package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +1 -1
  122. package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +1 -1
  123. package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +1 -1
  124. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +10 -6
  125. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +9 -6
  126. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +8 -6
  127. package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
  128. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +10 -8
  129. package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +8 -5
  130. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +38 -20
  131. package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +15 -25
  132. package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +10 -8
  133. package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +9 -6
  134. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +7 -5
  135. package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +8 -5
  136. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +6 -4
  137. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +10 -9
  138. package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +1 -1
  139. package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +1 -1
  140. package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
  141. package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +9 -6
  142. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +22 -12
  143. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +18 -15
  144. package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +53 -28
  145. package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +7 -5
  146. package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
  147. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +19 -15
  148. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +13 -10
  149. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +10 -6
  150. package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
  151. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +3 -13
  152. package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +12 -8
  153. package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +13 -8
  154. package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
  155. package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +10 -8
  156. package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
  157. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +41 -16
  158. package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
  159. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +7 -4
  160. package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +24 -23
  161. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +52 -34
  162. package/templates/storefront-nextjs-shadcn/components/layout/language-switcher.tsx +54 -0
  163. package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +33 -30
  164. package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +27 -24
  165. package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
  166. package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
  167. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +32 -42
  168. package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
  169. package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
  170. package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
  171. package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +6 -14
  172. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +4 -2
  173. package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +72 -0
  174. package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +87 -0
  175. package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +140 -0
  176. package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
  177. package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
  178. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +11 -37
  179. package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
  180. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +179 -124
  181. package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
  182. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +3 -7
  183. package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
  184. package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
  185. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +44 -19
  186. package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
  187. package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
  188. package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
  189. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +26 -34
  190. package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
  191. package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
  192. package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
  193. package/templates/storefront-nextjs-shadcn/components/providers/language-sync-provider.tsx +27 -0
  194. package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +63 -0
  195. package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
  196. package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
  197. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +59 -72
  198. package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +7 -4
  199. package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
  200. package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +12 -9
  201. package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +23 -12
  202. package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
  203. package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
  204. package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
  205. package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
  206. package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
  207. package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
  208. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +7 -4
  209. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +4 -2
  210. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +2 -10
  211. package/templates/storefront-nextjs-shadcn/generated/graphql.ts +13387 -0
  212. package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
  213. package/templates/storefront-nextjs-shadcn/hooks/index.ts +3 -0
  214. package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
  215. package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
  216. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +34 -229
  217. package/templates/storefront-nextjs-shadcn/hooks/use-cart-di.ts +67 -0
  218. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +16 -12
  219. package/templates/storefront-nextjs-shadcn/i18n/navigation.ts +12 -0
  220. package/templates/storefront-nextjs-shadcn/i18n/request.ts +17 -0
  221. package/templates/storefront-nextjs-shadcn/i18n/routing.ts +17 -0
  222. package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
  223. package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
  224. package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +33 -0
  225. package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
  226. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +720 -632
  227. package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +88 -0
  228. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +132 -182
  229. package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
  230. package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
  231. package/templates/storefront-nextjs-shadcn/messages/en.json +869 -0
  232. package/templates/storefront-nextjs-shadcn/messages/pl.json +869 -0
  233. package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
  234. package/templates/storefront-nextjs-shadcn/next.config.ts +6 -5
  235. package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
  236. package/templates/storefront-nextjs-shadcn/package.json +14 -14
  237. package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
  238. package/templates/storefront-nextjs-shadcn/proxy.ts +115 -47
  239. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +24 -56
  240. package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
  241. package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
  242. package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
  243. package/templates/storefront-nextjs-shadcn/wrangler.toml +11 -0
  244. package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
  245. package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
  246. package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
  247. package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
  248. package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
  249. package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
  250. package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
  251. package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
  252. package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +0 -215
  253. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +0 -128
  254. package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +0 -80
  255. package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +0 -171
  256. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +0 -78
  257. package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +0 -192
  258. package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
  259. package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
  260. package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
  261. package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
  262. package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
  263. package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
  264. package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
  265. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
  266. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
  267. package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
  268. package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
  269. package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
  270. package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
  271. package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
  272. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/page.tsx +0 -0
  273. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/[slug]/page.tsx +0 -0
  274. /package/templates/storefront-nextjs-shadcn/app/{returns → [locale]/returns}/page.tsx +0 -0
  275. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/page.tsx +0 -0
  276. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/search-client.tsx +0 -0
  277. /package/templates/storefront-nextjs-shadcn/app/{shipping → [locale]/shipping}/page.tsx +0 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Centralized React Query key definitions.
3
+ *
4
+ * All query keys in one place ensures:
5
+ * - Consistent cache invalidation across hooks
6
+ * - No key collisions or typos
7
+ * - Easy discovery of all cached data
8
+ * - Currency-aware and language-aware keys for automatic refetch on change
9
+ *
10
+ * Convention:
11
+ * - `all()` — matches ALL queries in this domain (for broad invalidation)
12
+ * - `list(...)` — paginated/filtered lists
13
+ * - `detail(...)` — single entity by ID/handle
14
+ * - Currency and language are included as flat strings for stable reference
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // In a hook:
19
+ * const currency = useCurrencyStore((s) => s.currency);
20
+ * const language = useLanguageStore((s) => s.language);
21
+ * useQuery({ queryKey: queryKeys.products.detail(slug, currency, language), ... });
22
+ *
23
+ * // Invalidation:
24
+ * queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
25
+ * ```
26
+ */
27
+ /** Currency/Language type — can be null before initialization */
28
+ type Currency = string | null;
29
+ type Language = string | null;
30
+
31
+ export const queryKeys = {
32
+ products: {
33
+ all: () => ['Product'] as const,
34
+ list: (vars?: Record<string, unknown>, currency?: Currency, language?: Language) =>
35
+ ['Products', vars, currency, language] as const,
36
+ detail: (handleOrId: string, currency: Currency, language?: Language) =>
37
+ ['Product', handleOrId, currency, language] as const,
38
+ search: (query: string, currency: Currency, language?: Language) =>
39
+ ['ProductSearch', query, currency, language] as const,
40
+ },
41
+
42
+ collections: {
43
+ all: () => ['Collection'] as const,
44
+ list: (vars?: Record<string, unknown>, currency?: Currency, language?: Language) =>
45
+ ['Collections', vars, currency, language] as const,
46
+ detail: (handleOrId: string, currency: Currency, language?: Language) =>
47
+ ['Collection', handleOrId, currency, language] as const,
48
+ },
49
+
50
+ categories: {
51
+ all: () => ['Category'] as const,
52
+ list: (currency: Currency, language?: Language) => ['Categories', currency, language] as const,
53
+ detail: (slugOrId: string, language?: Language) => ['Category', slugOrId, language] as const,
54
+ },
55
+
56
+ filters: {
57
+ all: () => ['AvailableFilters'] as const,
58
+ forContext: (input?: Record<string, unknown> | null, currency?: Currency, language?: Language) =>
59
+ ['AvailableFilters', input, currency, language] as const,
60
+ },
61
+
62
+ cart: {
63
+ all: () => ['Cart'] as const,
64
+ detail: (cartId: string | null, currency: Currency) =>
65
+ ['Cart', cartId, currency] as const,
66
+ },
67
+
68
+ checkout: {
69
+ all: () => ['Checkout'] as const,
70
+ detail: (checkoutId: string | null, currency: Currency) =>
71
+ ['Checkout', checkoutId, currency] as const,
72
+ },
73
+
74
+ customer: {
75
+ all: () => ['Customer'] as const,
76
+ detail: (token: string) => ['Customer', token] as const,
77
+ order: (orderId: string, currency: Currency) => ['CustomerOrder', orderId, currency] as const,
78
+ },
79
+
80
+ loyalty: {
81
+ member: (currency: Currency) => ['LoyaltyMember', currency] as const,
82
+ rewards: (currency: Currency) => ['LoyaltyRewards', currency] as const,
83
+ transactions: (vars?: Record<string, unknown>, currency?: Currency) =>
84
+ ['LoyaltyTransactions', vars, currency] as const,
85
+ settings: () => ['LoyaltySettings'] as const,
86
+ referralStats: () => ['ReferralStats'] as const,
87
+ },
88
+ } as const;
@@ -1,67 +1,83 @@
1
1
  import { cache } from 'react';
2
- import { GraphQLClient } from 'graphql-request';
3
- import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
4
- import { getCurrencyFromCookieAsync } from '@/lib/currency/';
2
+ import { getStorefrontClient } from '@doswiftly/storefront-sdk/react/server';
3
+ import { getCurrencyFromCookieAsync } from '@doswiftly/storefront-sdk/react';
4
+ import { CURRENCY_HEADER_NAME } from '@doswiftly/storefront-sdk';
5
+ import type { NormalizedProductsResult, NormalizedCollectionsResult } from './types';
6
+ import type { TypedDocumentString } from '@/generated/graphql';
7
+ import { graphqlConfig } from './config';
5
8
 
6
- // Import config - will be injected by CLI during template generation
7
- let config: {
8
- shop: { slug: string };
9
- api: { url: string };
10
- } | null = null;
9
+ // Static imports Documents
10
+ import {
11
+ ShopDocument,
12
+ ProductDocument,
13
+ ProductsDocument,
14
+ CollectionsDocument,
15
+ CollectionDocument,
16
+ CategoriesDocument,
17
+ CategoryDocument,
18
+ AvailableFiltersDocument,
19
+ CustomerDocument,
20
+ } from '@/generated/graphql';
11
21
 
12
- try {
13
- // Dynamic import to handle cases where config doesn't exist yet
14
- const configModule = require('@/doswiftly.config');
15
- config = configModule.default || configModule;
16
- } catch (error) {
17
- // Fallback to environment variables if config file doesn't exist
18
- config = {
19
- shop: {
20
- slug: process.env.NEXT_PUBLIC_SHOP_SLUG || 'demo-shop',
21
- },
22
- api: {
23
- url: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
24
- },
25
- };
26
- }
22
+ // Static imports — Types
23
+ import type {
24
+ ShopQuery,
25
+ ProductQuery,
26
+ ProductQueryVariables,
27
+ ProductsQuery,
28
+ ProductsQueryVariables,
29
+ ProductSortKeys,
30
+ CollectionsQuery,
31
+ CollectionsQueryVariables,
32
+ CollectionSortKeys,
33
+ CollectionQuery,
34
+ CollectionQueryVariables,
35
+ CategoriesQuery,
36
+ CategoryQuery,
37
+ CategoryQueryVariables,
38
+ AvailableFiltersQuery,
39
+ AvailableFiltersQueryVariables,
40
+ AvailableFiltersInput,
41
+ CustomerQuery,
42
+ CustomerQueryVariables,
43
+ } from '@/generated/graphql';
27
44
 
28
- /**
29
- * Cached GraphQL client factory for Server Components
30
- *
31
- * Uses React cache() to deduplicate requests within a single render pass.
32
- * Server-side requests now include X-Preferred-Currency header from cookie
33
- * for SSR currency consistency.
34
- *
35
- * Note: This is an async function in Next.js 15+ because cookies() is async.
36
- *
37
- * @returns GraphQL client configured for server-side usage with currency support
38
- */
39
- export const getClient = cache(async () => {
40
- // Read currency from cookie (SSR-safe, async in Next.js 15+)
41
- const currency = await getCurrencyFromCookieAsync();
42
-
43
- return new GraphQLClient(`${config!.api.url}/storefront/graphql`, {
44
- headers: {
45
- 'X-Shop-Slug': config!.shop.slug,
46
- // Include X-Preferred-Currency from cookie for SSR consistency
47
- ...(currency && { 'X-Preferred-Currency': currency }),
48
- },
49
- });
50
- });
45
+ // ---------------------------------------------------------------------------
46
+ // Generic request helper with React cache
47
+ // ---------------------------------------------------------------------------
51
48
 
52
49
  /**
53
- * Generic request helper with React cache
54
- *
55
- * @param document - TypedDocumentNode from codegen
56
- * @param variables - Query variables
57
- * @returns Query result
50
+ * Generic request helper with React cache.
51
+ *
52
+ * Uses React cache() to deduplicate requests within a single render pass.
53
+ * Server-side requests include X-Preferred-Currency header from cookie.
58
54
  */
59
55
  export const request = cache(async <TResult, TVariables>(
60
- document: TypedDocumentNode<TResult, TVariables>,
61
- variables?: TVariables
56
+ document: TypedDocumentString<TResult, TVariables>,
57
+ variables?: TVariables,
58
+ extraHeaders?: Record<string, string>,
62
59
  ): Promise<TResult> => {
63
- const client = await getClient();
64
- return client.request(document, variables as any);
60
+ // Get currency from cookie for server-side requests
61
+ let currency: string | null = null;
62
+ try {
63
+ currency = await getCurrencyFromCookieAsync();
64
+ } catch {
65
+ // cookies() unavailable outside request scope (generateStaticParams, build time)
66
+ }
67
+
68
+ const headers: Record<string, string> = {
69
+ ...(currency && { [CURRENCY_HEADER_NAME]: currency }),
70
+ ...extraHeaders,
71
+ };
72
+
73
+ // Use a fresh client with currency header for this request
74
+ const requestClient = getStorefrontClient({
75
+ apiUrl: graphqlConfig.apiUrl,
76
+ shopSlug: graphqlConfig.shopSlug,
77
+ defaultHeaders: headers,
78
+ });
79
+
80
+ return requestClient.query<TResult>(document.toString(), variables as Record<string, unknown>);
65
81
  });
66
82
 
67
83
  // ============================================================================
@@ -70,104 +86,49 @@ export const request = cache(async <TResult, TVariables>(
70
86
 
71
87
  /**
72
88
  * Fetch shop data with currency configuration
73
- *
74
- * Used in root layout to initialize currency store.
75
- * Cached per render to avoid duplicate requests.
76
- *
77
- * @returns Shop query result
78
- *
79
- * @example
80
- * ```typescript
81
- * // app/layout.tsx
82
- * import { fetchShop } from '@/lib/graphql/server';
83
- *
84
- * export default async function RootLayout() {
85
- * const data = await fetchShop();
86
- * return <CurrencyProvider shopData={data.shop}>...</CurrencyProvider>;
87
- * }
88
- * ```
89
89
  */
90
- export const fetchShop = cache(async () => {
91
- // Import generated types dynamically to avoid circular dependencies
92
- const { ShopDocument } = await import('@/generated/graphql');
93
- return request(ShopDocument, {});
90
+ export const fetchShop = cache(async (): Promise<ShopQuery> => {
91
+ return request(ShopDocument);
94
92
  });
95
93
 
96
94
  /**
97
95
  * Fetch single product by handle or ID
98
- *
99
- * Returns product in base currency for SSG compatibility.
100
- * Client components should refetch with preferred currency if needed.
101
- *
102
- * @param handleOrId - Product handle (string) or ID
103
- * @returns Product query result
104
- *
105
- * @example
106
- * ```typescript
107
- * // app/products/[handle]/page.tsx
108
- * import { fetchProduct } from '@/lib/graphql/server';
109
- *
110
- * export default async function ProductPage({ params }) {
111
- * const data = await fetchProduct(params.handle);
112
- * return <ProductClient initialProduct={data.product} />;
113
- * }
114
- * ```
115
96
  */
116
- export const fetchProduct = cache(async (handleOrId: string) => {
97
+ export const fetchProduct = cache(async (handleOrId: string): Promise<ProductQuery> => {
117
98
  if (!handleOrId) {
118
99
  throw new Error('Product handle or ID is required');
119
100
  }
120
-
121
- const { ProductDocument } = await import('@/generated/graphql');
122
-
123
- // Determine if it's an ID or handle
101
+
124
102
  const isId = handleOrId.startsWith('gid://');
125
-
126
- return request(ProductDocument, {
127
- ...(isId ? { id: handleOrId } : { handle: handleOrId }),
128
- });
103
+ const variables: ProductQueryVariables = isId
104
+ ? { id: handleOrId }
105
+ : { handle: handleOrId };
106
+
107
+ return request(ProductDocument, variables);
129
108
  });
130
109
 
131
110
  /**
132
111
  * Fetch products with pagination and normalization
133
- *
134
- * Automatically normalizes GraphQL edges/nodes structure to flat arrays
135
- * for easier consumption in components.
136
- *
137
- * @param variables - Query variables (first, after, query, sortKey, reverse)
138
- * @returns Normalized products response
139
- *
140
- * @example
141
- * ```typescript
142
- * // app/products/page.tsx
143
- * import { fetchProducts } from '@/lib/graphql/server';
144
- *
145
- * export default async function ProductsPage() {
146
- * const { products, pageInfo } = await fetchProducts({ first: 20 });
147
- * return products.map(product => <ProductCard key={product.id} product={product} />);
148
- * }
149
- * ```
150
112
  */
151
113
  export const fetchProducts = cache(async (variables?: {
152
114
  first?: number;
153
115
  after?: string;
154
116
  query?: string;
155
- sortKey?: string;
117
+ sortKey?: ProductSortKeys;
156
118
  reverse?: boolean;
157
- }) => {
158
- const { ProductsDocument } = await import('@/generated/graphql');
159
-
160
- const data = await request(ProductsDocument, {
119
+ }): Promise<NormalizedProductsResult> => {
120
+ const graphqlVariables: ProductsQueryVariables = {
161
121
  first: variables?.first ?? 20,
162
122
  after: variables?.after,
163
123
  query: variables?.query,
164
- sortKey: variables?.sortKey as any,
124
+ sortKey: variables?.sortKey,
165
125
  reverse: variables?.reverse,
166
- });
167
-
168
- // Normalize: edges/nodes flat array
126
+ };
127
+
128
+ const data = await request(ProductsDocument, graphqlVariables);
129
+
169
130
  return {
170
- products: data.products.edges.map((edge: any) => edge.node),
131
+ products: data.products.edges.map((edge) => edge.node),
171
132
  pageInfo: data.products.pageInfo,
172
133
  totalCount: data.products.totalCount,
173
134
  };
@@ -175,37 +136,26 @@ export const fetchProducts = cache(async (variables?: {
175
136
 
176
137
  /**
177
138
  * Fetch collections with pagination and normalization
178
- *
179
- * @param variables - Query variables
180
- * @returns Normalized collections response
181
- *
182
- * @example
183
- * ```typescript
184
- * import { fetchCollections } from '@/lib/graphql/server';
185
- *
186
- * const { collections } = await fetchCollections({ first: 10 });
187
- * ```
188
139
  */
189
140
  export const fetchCollections = cache(async (variables?: {
190
141
  first?: number;
191
142
  after?: string;
192
143
  query?: string;
193
- sortKey?: string;
144
+ sortKey?: CollectionSortKeys;
194
145
  reverse?: boolean;
195
- }) => {
196
- const { CollectionsDocument } = await import('@/generated/graphql');
197
-
198
- const data = await request(CollectionsDocument, {
146
+ }): Promise<NormalizedCollectionsResult> => {
147
+ const graphqlVariables: CollectionsQueryVariables = {
199
148
  first: variables?.first ?? 20,
200
149
  after: variables?.after,
201
150
  query: variables?.query,
202
- sortKey: variables?.sortKey as any,
151
+ sortKey: variables?.sortKey,
203
152
  reverse: variables?.reverse,
204
- });
205
-
206
- // Normalize: edges/nodes flat array
153
+ };
154
+
155
+ const data = await request(CollectionsDocument, graphqlVariables);
156
+
207
157
  return {
208
- collections: data.collections.edges.map((edge: any) => edge.node),
158
+ collections: data.collections.edges.map((edge) => edge.node),
209
159
  pageInfo: data.collections.pageInfo,
210
160
  totalCount: data.collections.totalCount,
211
161
  };
@@ -213,55 +163,55 @@ export const fetchCollections = cache(async (variables?: {
213
163
 
214
164
  /**
215
165
  * Fetch single collection by handle or ID
216
- *
217
- * @param handleOrId - Collection handle or ID
218
- * @returns Collection query result
219
- *
220
- * @example
221
- * ```typescript
222
- * import { fetchCollection } from '@/lib/graphql/server';
223
- *
224
- * const data = await fetchCollection('featured-products');
225
- * ```
226
166
  */
227
- export const fetchCollection = cache(async (handleOrId: string) => {
228
- const { CollectionDocument } = await import('@/generated/graphql');
229
-
167
+ export const fetchCollection = cache(async (handleOrId: string): Promise<CollectionQuery> => {
230
168
  const isId = handleOrId.startsWith('gid://');
231
-
232
- return request(CollectionDocument, {
233
- ...(isId ? { id: handleOrId } : { handle: handleOrId }),
234
- });
169
+ const variables: CollectionQueryVariables = isId
170
+ ? { id: handleOrId }
171
+ : { handle: handleOrId };
172
+
173
+ return request(CollectionDocument, variables);
235
174
  });
236
175
 
237
176
  /**
238
177
  * Fetch categories from GraphQL API
239
- *
240
- * @returns Categories query result with tree structure
241
178
  */
242
- export const fetchCategories = cache(async () => {
243
- const { CategoriesDocument } = await import('@/generated/graphql');
244
- return request(CategoriesDocument, {});
179
+ export const fetchCategories = cache(async (): Promise<CategoriesQuery> => {
180
+ return request(CategoriesDocument);
181
+ });
182
+
183
+ /**
184
+ * Fetch single category by slug or ID
185
+ */
186
+ export const fetchCategory = cache(async (slugOrId: string): Promise<CategoryQuery> => {
187
+ const isId = slugOrId.startsWith('gid://');
188
+ const variables: CategoryQueryVariables = isId
189
+ ? { id: slugOrId }
190
+ : { slug: slugOrId };
191
+
192
+ return request(CategoryDocument, variables);
193
+ });
194
+
195
+ /**
196
+ * Fetch available filters for product listing (SSR)
197
+ */
198
+ export const fetchAvailableFilters = cache(async (
199
+ input?: AvailableFiltersInput,
200
+ ): Promise<AvailableFiltersQuery> => {
201
+ const variables: AvailableFiltersQueryVariables = { input: input || null };
202
+ return request(AvailableFiltersDocument, variables);
245
203
  });
246
204
 
247
205
  /**
248
206
  * Fetch customer data (requires access token)
249
- *
250
- * @param accessToken - Customer access token
251
- * @returns Customer query result with addresses and orders
252
207
  */
253
- export const fetchCustomer = cache(async (accessToken: string) => {
254
- const { CustomerDocument } = await import('@/generated/graphql');
255
- return request(CustomerDocument, { customerAccessToken: accessToken });
208
+ export const fetchCustomer = cache(async (accessToken: string): Promise<CustomerQuery> => {
209
+ const variables: CustomerQueryVariables = { customerAccessToken: accessToken };
210
+ return request(CustomerDocument, variables);
256
211
  });
257
212
 
258
213
  // ============================================================================
259
214
  // TYPE EXPORTS
260
215
  // ============================================================================
261
216
 
262
- /**
263
- * Normalized response types for helper functions
264
- * These types will be inferred from generated GraphQL types
265
- */
266
- export type NormalizedProductsResponse = Awaited<ReturnType<typeof fetchProducts>>;
267
- export type NormalizedCollectionsResponse = Awaited<ReturnType<typeof fetchCollections>>;
217
+ export type { NormalizedProductsResult, NormalizedCollectionsResult } from './types';
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared domain types derived from GraphQL codegen.
3
+ *
4
+ * Two categories of types:
5
+ *
6
+ * 1. **Query-derived types** — extracted from query response shapes.
7
+ * Use when you need the EXACT shape returned by a specific query.
8
+ *
9
+ * 2. **Fragment-derived types** — from template-local fragments.
10
+ * Use for component props to enforce fragment-first architecture.
11
+ * Fragment = Component data contract.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // For a product card component (fragment-first):
16
+ * import type { ProductCardFields } from '@/lib/graphql/types';
17
+ * interface Props { product: ProductCardFields }
18
+ *
19
+ * // For a server helper return type (query-derived):
20
+ * import type { NormalizedProductsResult } from '@/lib/graphql/types';
21
+ * ```
22
+ */
23
+ import type {
24
+ ProductsQuery,
25
+ CollectionsQuery,
26
+ CategoriesQuery,
27
+ Category,
28
+ } from '@/generated/graphql';
29
+
30
+ // Fragment types → see lib/graphql/fragments.ts
31
+
32
+ // ============================================================================
33
+ // QUERY-DERIVED TYPES (from storefront-operations queries)
34
+ // ============================================================================
35
+
36
+ /** Single product node from Products list query */
37
+ export type ProductNode = ProductsQuery['products']['edges'][number]['node'];
38
+
39
+ /** Single collection node from Collections list query */
40
+ export type CollectionNode = CollectionsQuery['collections']['edges'][number]['node'];
41
+
42
+ // ============================================================================
43
+ // NORMALIZED RESULT TYPES (for server.ts and hooks.ts)
44
+ // ============================================================================
45
+
46
+ export interface NormalizedProductsResult {
47
+ products: ProductNode[];
48
+ pageInfo: ProductsQuery['products']['pageInfo'];
49
+ totalCount: number;
50
+ }
51
+
52
+ export interface NormalizedCollectionsResult {
53
+ collections: CollectionNode[];
54
+ pageInfo: CollectionsQuery['collections']['pageInfo'];
55
+ totalCount: number;
56
+ }
57
+
58
+ export interface NormalizedCategoriesResult {
59
+ categories: Category[];
60
+ roots: CategoriesQuery['categories']['roots'];
61
+ totalCount: number;
62
+ }
@@ -70,20 +70,3 @@ export const themeConfig = {
70
70
  } as const;
71
71
 
72
72
  export type Theme = (typeof themeConfig.themes)[number];
73
-
74
- /**
75
- * Get theme colors for a specific theme
76
- */
77
- export function getThemeColors(theme: "light" | "dark") {
78
- return themeConfig.colors[theme];
79
- }
80
-
81
- /**
82
- * Generate CSS variables for theme
83
- */
84
- export function generateThemeVariables(theme: "light" | "dark") {
85
- const colors = getThemeColors(theme);
86
- return Object.entries(colors)
87
- .map(([key, value]) => `--${key}: ${value};`)
88
- .join("\n ");
89
- }