@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.
- package/README.md +23 -323
- package/dist/commands/check.js +1 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/deploy.d.ts +20 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +249 -17
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +4 -4
- package/dist/commands/sdk.js +5 -5
- package/dist/commands/sdk.js.map +1 -1
- package/dist/commands/template.js +4 -4
- package/dist/commands/template.js.map +1 -1
- package/dist/commands/types.js +5 -5
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/verify.js +2 -2
- package/dist/commands/verify.js.map +1 -1
- package/dist/lib/package-manager.d.ts +1 -1
- package/dist/lib/package-manager.js +1 -1
- package/package.json +4 -4
- package/templates/storefront-minimal/.github/workflows/build-template.yml +10 -0
- package/templates/storefront-minimal/wrangler.toml +11 -0
- package/templates/storefront-nextjs/.github/workflows/build-template.yml +10 -0
- package/templates/storefront-nextjs/README.md +16 -12
- package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
- package/templates/storefront-nextjs/app/account/page.tsx +2 -2
- package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
- package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
- package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
- package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
- package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
- package/templates/storefront-nextjs/app/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/page.tsx +2 -2
- package/templates/storefront-nextjs/app/search/page.tsx +1 -1
- package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
- package/templates/storefront-nextjs/components/providers.tsx +1 -1
- package/templates/storefront-nextjs/lib/currency.tsx +3 -3
- package/templates/storefront-nextjs/lib/format.ts +1 -1
- package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
- package/templates/storefront-nextjs/package.dev.json +1 -1
- package/templates/storefront-nextjs/package.json +1 -1
- package/templates/storefront-nextjs/package.json.template +1 -1
- package/templates/storefront-nextjs/wrangler.toml +11 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +10 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
- package/templates/storefront-nextjs-shadcn/CLAUDE.md +172 -35
- package/templates/storefront-nextjs-shadcn/README.md +29 -162
- package/templates/storefront-nextjs-shadcn/app/{about → [locale]/about}/page.tsx +17 -14
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/addresses/page.tsx +226 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/error.tsx +46 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loyalty/page.tsx +89 -193
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/loading.tsx +60 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/page.tsx +119 -0
- package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/tracking/page.tsx +27 -25
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/page.tsx +101 -0
- package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/page.tsx +9 -7
- package/templates/storefront-nextjs-shadcn/app/[locale]/account/settings/page.tsx +208 -0
- package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx +24 -17
- package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/login/page.tsx +5 -2
- package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/register/page.tsx +5 -2
- package/templates/storefront-nextjs-shadcn/app/[locale]/blog/[slug]/loading.tsx +17 -0
- package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/page.tsx +44 -3
- package/templates/storefront-nextjs-shadcn/app/[locale]/blog/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/page.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/app/[locale]/cart/loading.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/page.tsx +20 -13
- package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/category-products-client.tsx +58 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/page.tsx +95 -0
- package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/page.tsx +21 -12
- package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/loading.tsx +31 -0
- package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/page.tsx +334 -253
- package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/success/[orderId]/page.tsx +36 -34
- package/templates/storefront-nextjs-shadcn/app/[locale]/collections/[handle]/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/page.tsx +6 -4
- package/templates/storefront-nextjs-shadcn/app/[locale]/collections/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/page.tsx +20 -12
- package/templates/storefront-nextjs-shadcn/app/{contact → [locale]/contact}/page.tsx +24 -21
- package/templates/storefront-nextjs-shadcn/app/{error.tsx → [locale]/error.tsx} +13 -8
- package/templates/storefront-nextjs-shadcn/app/[locale]/layout.tsx +92 -0
- package/templates/storefront-nextjs-shadcn/app/{not-found.tsx → [locale]/not-found.tsx} +13 -18
- package/templates/storefront-nextjs-shadcn/app/{page.tsx → [locale]/page.tsx} +8 -4
- package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/loading.tsx +29 -0
- package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/page.tsx +17 -14
- package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/product-client.tsx +18 -62
- package/templates/storefront-nextjs-shadcn/app/[locale]/products/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/page.tsx +6 -3
- package/templates/storefront-nextjs-shadcn/app/[locale]/products/products-client.tsx +450 -0
- package/templates/storefront-nextjs-shadcn/app/[locale]/search/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/{wishlist → [locale]/wishlist}/page.tsx +27 -28
- package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
- package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
- package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
- package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
- package/templates/storefront-nextjs-shadcn/app/layout.tsx +8 -35
- package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
- package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +25 -20
- package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +11 -10
- package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +17 -13
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +42 -30
- package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +18 -16
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +37 -58
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +85 -66
- package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +10 -6
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +9 -6
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +8 -6
- package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +10 -8
- package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +38 -20
- package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +15 -25
- package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +10 -8
- package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +9 -6
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +7 -5
- package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +6 -4
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +10 -9
- package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
- package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +9 -6
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +22 -12
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +18 -15
- package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +53 -28
- package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +7 -5
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +19 -15
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +13 -10
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +10 -6
- package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +3 -13
- package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +12 -8
- package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +13 -8
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
- package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +10 -8
- package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +41 -16
- package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +7 -4
- package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +24 -23
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +52 -34
- package/templates/storefront-nextjs-shadcn/components/layout/language-switcher.tsx +54 -0
- package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +33 -30
- package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +27 -24
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
- package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +32 -42
- package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
- package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
- package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +6 -14
- package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +4 -2
- package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +72 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +87 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +140 -0
- package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +11 -37
- package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +179 -124
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +3 -7
- package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
- package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +44 -19
- package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
- package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +26 -34
- package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
- package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
- package/templates/storefront-nextjs-shadcn/components/providers/language-sync-provider.tsx +27 -0
- package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +63 -0
- package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
- package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +59 -72
- package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +7 -4
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +12 -9
- package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +23 -12
- package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
- package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
- package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
- package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
- package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +7 -4
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +4 -2
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +2 -10
- package/templates/storefront-nextjs-shadcn/generated/graphql.ts +13387 -0
- package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +3 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +34 -229
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-di.ts +67 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +16 -12
- package/templates/storefront-nextjs-shadcn/i18n/navigation.ts +12 -0
- package/templates/storefront-nextjs-shadcn/i18n/request.ts +17 -0
- package/templates/storefront-nextjs-shadcn/i18n/routing.ts +17 -0
- package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
- package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
- package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +33 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +720 -632
- package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +88 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +132 -182
- package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
- package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
- package/templates/storefront-nextjs-shadcn/messages/en.json +869 -0
- package/templates/storefront-nextjs-shadcn/messages/pl.json +869 -0
- package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
- package/templates/storefront-nextjs-shadcn/next.config.ts +6 -5
- package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
- package/templates/storefront-nextjs-shadcn/package.json +14 -14
- package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
- package/templates/storefront-nextjs-shadcn/proxy.ts +115 -47
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +24 -56
- package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
- package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
- package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
- package/templates/storefront-nextjs-shadcn/wrangler.toml +11 -0
- package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
- package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
- package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
- package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
- package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
- package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
- package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
- package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +0 -215
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +0 -128
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +0 -80
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +0 -171
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +0 -78
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +0 -192
- package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
- package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
- package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
- package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
- package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
- package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
- package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
- package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
- package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
- package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
- package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
- package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
- /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/page.tsx +0 -0
- /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/[slug]/page.tsx +0 -0
- /package/templates/storefront-nextjs-shadcn/app/{returns → [locale]/returns}/page.tsx +0 -0
- /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/page.tsx +0 -0
- /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/search-client.tsx +0 -0
- /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 {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
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
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
56
|
-
*
|
|
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:
|
|
61
|
-
variables?: TVariables
|
|
56
|
+
document: TypedDocumentString<TResult, TVariables>,
|
|
57
|
+
variables?: TVariables,
|
|
58
|
+
extraHeaders?: Record<string, string>,
|
|
62
59
|
): Promise<TResult> => {
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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
|
-
|
|
127
|
-
|
|
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?:
|
|
117
|
+
sortKey?: ProductSortKeys;
|
|
156
118
|
reverse?: boolean;
|
|
157
|
-
}) => {
|
|
158
|
-
const
|
|
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
|
|
124
|
+
sortKey: variables?.sortKey,
|
|
165
125
|
reverse: variables?.reverse,
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const data = await request(ProductsDocument, graphqlVariables);
|
|
129
|
+
|
|
169
130
|
return {
|
|
170
|
-
products: data.products.edges.map((edge
|
|
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?:
|
|
144
|
+
sortKey?: CollectionSortKeys;
|
|
194
145
|
reverse?: boolean;
|
|
195
|
-
}) => {
|
|
196
|
-
const
|
|
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
|
|
151
|
+
sortKey: variables?.sortKey,
|
|
203
152
|
reverse: variables?.reverse,
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const data = await request(CollectionsDocument, graphqlVariables);
|
|
156
|
+
|
|
207
157
|
return {
|
|
208
|
-
collections: data.collections.edges.map((edge
|
|
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
|
-
|
|
233
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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
|
|
255
|
-
return request(CustomerDocument,
|
|
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
|
-
}
|