@doswiftly/cli 0.1.18 → 0.1.19
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.map +1 -1
- package/dist/commands/deploy.js +39 -20
- 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 +1 -1
- 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-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 +148 -35
- package/templates/storefront-nextjs-shadcn/README.md +29 -162
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +98 -91
- package/templates/storefront-nextjs-shadcn/app/account/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/account/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +53 -162
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/loading.tsx +60 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +36 -47
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +46 -29
- package/templates/storefront-nextjs-shadcn/app/account/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +108 -71
- 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/auth/forgot-password/page.tsx +10 -5
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/loading.tsx +17 -0
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +43 -2
- package/templates/storefront-nextjs-shadcn/app/blog/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/app/cart/loading.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +6 -3
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/category-products-client.tsx +56 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +76 -59
- package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +8 -4
- package/templates/storefront-nextjs-shadcn/app/checkout/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/loading.tsx +31 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +116 -79
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/app/collections/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +7 -4
- 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 +46 -11
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/loading.tsx +29 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +6 -6
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +15 -61
- package/templates/storefront-nextjs-shadcn/app/products/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +405 -151
- package/templates/storefront-nextjs-shadcn/app/search/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
- package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +26 -24
- package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +9 -9
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +11 -37
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +37 -23
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +4 -3
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +22 -7
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +3 -3
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +2 -12
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
- package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +4 -4
- package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +33 -23
- 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 +10 -19
- 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/b2b-price-display.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +69 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +84 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +138 -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 +3 -31
- package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +176 -123
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +2 -2
- 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 +19 -7
- 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 +1 -7
- 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/stores-provider.tsx +30 -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 +3 -2
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
- 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-icon.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/generated/graphql.ts +12779 -0
- package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +2 -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 +51 -19
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +13 -9
- 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 +32 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +687 -632
- package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +86 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +131 -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/next-env.d.ts +6 -0
- package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
- package/templates/storefront-nextjs-shadcn/package.json +12 -13
- package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
- package/templates/storefront-nextjs-shadcn/proxy.ts +3 -4
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +41 -39
- 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/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/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
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Preview Deployment
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
preview:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
env:
|
|
11
|
+
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
|
|
12
|
+
NEXT_PUBLIC_SHOP_SLUG: ${{ secrets.NEXT_PUBLIC_SHOP_SLUG }}
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Detect package manager
|
|
17
|
+
id: pm
|
|
18
|
+
run: |
|
|
19
|
+
if [ -f pnpm-lock.yaml ]; then
|
|
20
|
+
echo "manager=pnpm" >> $GITHUB_OUTPUT
|
|
21
|
+
echo "install=pnpm install --frozen-lockfile" >> $GITHUB_OUTPUT
|
|
22
|
+
elif [ -f yarn.lock ]; then
|
|
23
|
+
echo "manager=yarn" >> $GITHUB_OUTPUT
|
|
24
|
+
echo "install=yarn install --frozen-lockfile" >> $GITHUB_OUTPUT
|
|
25
|
+
else
|
|
26
|
+
echo "manager=npm" >> $GITHUB_OUTPUT
|
|
27
|
+
echo "install=npm ci" >> $GITHUB_OUTPUT
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
- name: Setup pnpm
|
|
31
|
+
if: steps.pm.outputs.manager == 'pnpm'
|
|
32
|
+
uses: pnpm/action-setup@v4
|
|
33
|
+
|
|
34
|
+
- uses: actions/setup-node@v4
|
|
35
|
+
with:
|
|
36
|
+
node-version: 20
|
|
37
|
+
cache: ${{ steps.pm.outputs.manager }}
|
|
38
|
+
|
|
39
|
+
- name: Install dependencies
|
|
40
|
+
run: ${{ steps.pm.outputs.install }}
|
|
41
|
+
|
|
42
|
+
- name: Deploy preview
|
|
43
|
+
run: |
|
|
44
|
+
npx --yes @doswiftly/cli@latest --version
|
|
45
|
+
npx @doswiftly/cli@latest deploy run --type PREVIEW --branch ${{ github.head_ref }}
|
|
46
|
+
env:
|
|
47
|
+
DOSWIFTLY_DEPLOY_TOKEN: ${{ secrets.DOSWIFTLY_DEPLOY_TOKEN }}
|
|
@@ -6,39 +6,87 @@ Ten plik jest synchronizowany do `storefronts/test-shop/` przez `pnpm sync:store
|
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
app/ # Next.js 15 App Router
|
|
9
|
-
├── layout.tsx # Root layout z
|
|
9
|
+
├── layout.tsx # Root layout z StorefrontProvider + QueryProvider
|
|
10
10
|
├── page.tsx # Homepage
|
|
11
|
-
├── products/ # Strony produktow
|
|
11
|
+
├── products/ # Strony produktow (SSR + client hydration)
|
|
12
12
|
├── collections/ # Strony kolekcji
|
|
13
|
-
├──
|
|
14
|
-
├──
|
|
15
|
-
├──
|
|
16
|
-
|
|
13
|
+
├── categories/ # Strony kategorii (SSR metadata + client products)
|
|
14
|
+
├── cart/ # Koszyk (client-only, Zustand + React Query)
|
|
15
|
+
├── checkout/ # Checkout (client-only, multi-step mutations)
|
|
16
|
+
├── account/ # Panel klienta (auth required)
|
|
17
|
+
├── auth/ # Login/Register
|
|
18
|
+
└── blog/ # Blog (SSR)
|
|
17
19
|
|
|
18
20
|
components/
|
|
19
21
|
├── product/ # ProductCard, ProductGrid, AddToCartButton
|
|
22
|
+
│ ├── product-card.fragment.graphql # Colocated fragment
|
|
23
|
+
│ ├── product-detail.fragment.graphql
|
|
24
|
+
│ └── product-variant.fragment.graphql
|
|
20
25
|
├── cart/ # CartDrawer, CartItem, CartSummary
|
|
21
|
-
|
|
26
|
+
│ └── cart-line.fragment.graphql
|
|
27
|
+
├── home/ # FeaturedCollections, Hero
|
|
28
|
+
│ └── collection-card.fragment.graphql
|
|
29
|
+
├── account/ # OrderCard, CustomerInfo
|
|
30
|
+
│ ├── order-summary.fragment.graphql
|
|
31
|
+
│ └── customer-info.fragment.graphql
|
|
22
32
|
├── layout/ # Header, Footer, Navigation
|
|
33
|
+
│ └── category-node.fragment.graphql
|
|
34
|
+
├── auth/ # LoginForm, RegisterForm
|
|
23
35
|
├── ui/ # shadcn/ui components
|
|
24
|
-
└── providers/ # QueryProvider,
|
|
36
|
+
└── providers/ # QueryProvider, ThemeProvider
|
|
25
37
|
|
|
26
38
|
lib/
|
|
27
39
|
├── graphql/
|
|
28
|
-
│ ├──
|
|
29
|
-
│ ├──
|
|
30
|
-
│
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
├──
|
|
36
|
-
└──
|
|
40
|
+
│ ├── config.ts # Centralized API config (SSOT for apiUrl, shopSlug)
|
|
41
|
+
│ ├── query-keys.ts # Centralized React Query keys
|
|
42
|
+
│ ├── client.ts # useExecute() hook — uses SDK StorefrontClient from Context
|
|
43
|
+
│ ├── server.ts # SSR helpers z React.cache()
|
|
44
|
+
│ ├── hooks.ts # React Query hooks (useProducts, useCart, etc.)
|
|
45
|
+
│ ├── types.ts # Domain types derived from codegen (query result shapes)
|
|
46
|
+
│ └── fragments.ts # Fragment type re-exports (component data contracts)
|
|
47
|
+
├── auth/
|
|
48
|
+
│ └── routes.ts # Route lists + re-exports AUTH_COOKIE_NAME/matchesRoute from SDK
|
|
49
|
+
└── theme/
|
|
50
|
+
└── theme-config.ts # Theme tokens (colors, storage key)
|
|
51
|
+
|
|
52
|
+
graphql/
|
|
53
|
+
└── custom.example.graphql # Example custom operations
|
|
54
|
+
|
|
55
|
+
stores/ # Zustand stores (Context pattern via SDK createStoreContext)
|
|
56
|
+
├── cart-store.ts # Cart UI state (cartId, isOpen) — items from server
|
|
57
|
+
├── checkout-store.ts # Checkout form state with persistence
|
|
58
|
+
└── wishlist-store.ts # Wishlist state with persistence
|
|
59
|
+
|
|
60
|
+
hooks/
|
|
61
|
+
├── use-auth.ts # Thin wrapper over SDK useAuth + httpOnly cookies
|
|
62
|
+
├── use-auth-sync.ts # Detects auth desync (cookie vs store)
|
|
63
|
+
├── use-cart-actions.ts # Cart mutations with debounce + race condition protection
|
|
64
|
+
├── use-cart-sync.ts # Cart data from server (maps GraphQL → CartItemData)
|
|
65
|
+
└── use-filter-params.ts # URL-driven filter state
|
|
37
66
|
|
|
38
67
|
generated/
|
|
39
|
-
└── graphql.ts # Auto-
|
|
68
|
+
└── graphql.ts # Auto-generated types + TypedDocumentString constants
|
|
40
69
|
```
|
|
41
70
|
|
|
71
|
+
## SDK Integration
|
|
72
|
+
|
|
73
|
+
Template importuje z `@doswiftly/storefront-sdk`:
|
|
74
|
+
- **Core (`.`)**: `AUTH_COOKIE_NAME`, `matchesRoute`, `createSetTokenHandler`, `createClearTokenHandler`, `createAuthTokenClient`, `formatPrice`, `formatAmount`, `sanitizeHtml`, `normalizeConnection`
|
|
75
|
+
- **React (`./react`)**: `StorefrontProvider`, `useAuthStore`, `useCurrencyStore`, `useAuthHydrated`, `useStorefrontClient`, `useHydrated`, `useDebouncedValue`, `createStoreContext`
|
|
76
|
+
- **Server (`./react/server`)**: `getStorefrontClient`, `getCurrencyFromCookieAsync`
|
|
77
|
+
- **Auth hooks**: `useAuth` (bazowy, owinięty w `hooks/use-auth.ts`)
|
|
78
|
+
|
|
79
|
+
**Store pattern**: Zustand stores używają `createStore()` (vanilla) + React Context via `createStoreContext()` from SDK.
|
|
80
|
+
Hooki `useAuthStore`/`useCurrencyStore` wymagają owinięcia w `StorefrontProvider`.
|
|
81
|
+
Template stores (cart, checkout, wishlist) wymagają `StoresProvider` (wewnątrz `StorefrontProvider`).
|
|
82
|
+
`useAuthHydrated()` zwraca `true` po rehydracji persist z localStorage.
|
|
83
|
+
`useHydrated()` zwraca `true` po hydration SSR → client.
|
|
84
|
+
|
|
85
|
+
Template NIE importuje z SDK:
|
|
86
|
+
- React Query hooks — są LOCAL w `lib/graphql/hooks.ts`
|
|
87
|
+
- Cart actions — LOCAL w `hooks/use-cart-actions.ts`
|
|
88
|
+
- Data types — LOCAL via codegen (`generated/graphql.ts`)
|
|
89
|
+
|
|
42
90
|
## Data Fetching
|
|
43
91
|
|
|
44
92
|
### Server Components (lib/graphql/server.ts):
|
|
@@ -59,38 +107,103 @@ const { data, isLoading } = useProducts({ first: 20 });
|
|
|
59
107
|
const addLines = useCartLinesAdd();
|
|
60
108
|
```
|
|
61
109
|
|
|
62
|
-
|
|
110
|
+
### SSR → Client Hydration Pattern:
|
|
111
|
+
```typescript
|
|
112
|
+
// Server Component (page.tsx)
|
|
113
|
+
const { product } = await fetchProduct(slug);
|
|
114
|
+
return <ProductClient product={product} />;
|
|
115
|
+
|
|
116
|
+
// Client Component (product-client.tsx)
|
|
117
|
+
const { data } = useProduct(handle, {
|
|
118
|
+
placeholderData: currencyMatches ? { product: initialProduct } : undefined,
|
|
119
|
+
});
|
|
120
|
+
// placeholderData shows SSR data while React Query refetches with correct currency
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Fragment-First Architecture (Colocated Fragments)
|
|
124
|
+
|
|
125
|
+
Fragments are **colocated** next to their components (Hydrogen/Relay pattern):
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
components/product/product-card.fragment.graphql → ProductCardFieldsFragment
|
|
129
|
+
components/cart/cart-line.fragment.graphql → CartLineFieldsFragment
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Import fragment types via the stable API layer, not directly from codegen:
|
|
63
133
|
|
|
64
|
-
### Cart Store:
|
|
65
134
|
```typescript
|
|
66
|
-
|
|
135
|
+
// Component uses fragment type for props:
|
|
136
|
+
import type { ProductCardFields } from '@/lib/graphql/fragments';
|
|
67
137
|
|
|
68
|
-
|
|
138
|
+
interface ProductCardProps {
|
|
139
|
+
product: ProductCardFields;
|
|
140
|
+
}
|
|
69
141
|
```
|
|
70
142
|
|
|
71
|
-
|
|
143
|
+
**Convention**: When a GraphQL fragment exists for data your component receives, use the fragment type — do NOT define a local interface.
|
|
144
|
+
|
|
145
|
+
Codegen picks up colocated fragments via `components/**/*.fragment.graphql` glob.
|
|
146
|
+
Run `pnpm codegen` after adding new `.fragment.graphql` files.
|
|
147
|
+
|
|
148
|
+
## Why fragmentMasking is disabled
|
|
149
|
+
|
|
150
|
+
`codegen.ts` sets `fragmentMasking: false`. This means:
|
|
151
|
+
- Fragment types are plain TS types (structural typing, no `$fragmentName` branding)
|
|
152
|
+
- Components can accept both fragment types and supertypes from query results
|
|
153
|
+
- Does NOT require `useFragment()` helpers (Relay pattern)
|
|
154
|
+
|
|
155
|
+
Trade-off: a component could technically access fields outside its fragment.
|
|
156
|
+
We accept this intentionally — simplicity and DX > strict data masking.
|
|
157
|
+
If the project scales to multiple teams, consider `fragmentMasking: true`.
|
|
158
|
+
|
|
159
|
+
## Query Keys
|
|
160
|
+
|
|
161
|
+
All React Query keys are centralized in `lib/graphql/query-keys.ts`:
|
|
162
|
+
|
|
72
163
|
```typescript
|
|
73
|
-
import {
|
|
164
|
+
import { queryKeys } from '@/lib/graphql/query-keys';
|
|
165
|
+
|
|
166
|
+
// Reading data:
|
|
167
|
+
useQuery({ queryKey: queryKeys.products.detail(slug, currency), ... });
|
|
74
168
|
|
|
75
|
-
|
|
169
|
+
// Invalidating:
|
|
170
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
76
171
|
```
|
|
77
172
|
|
|
173
|
+
## Cart Race Condition Protection
|
|
174
|
+
|
|
175
|
+
Cart mutations use three layers of protection:
|
|
176
|
+
1. **cancelQueries** — Cancel in-flight cart queries before mutation
|
|
177
|
+
2. **Debounce** — 500ms debounce on quantity updates
|
|
178
|
+
3. **onSettled invalidation** — Refetch cart after mutation success OR error
|
|
179
|
+
|
|
78
180
|
## Konwencje
|
|
79
181
|
|
|
80
182
|
1. **Client vs Server**: Dodaj `"use client"` tylko gdy potrzebne (hooks, interaktywnosc)
|
|
81
|
-
2. **
|
|
82
|
-
3. **
|
|
83
|
-
4. **
|
|
84
|
-
5. **
|
|
183
|
+
2. **Fragment types**: Import z `@/lib/graphql/fragments`, NIE z `@/generated/graphql`
|
|
184
|
+
3. **No local interfaces**: Gdy istnieje fragment type, uzywaj go zamiast local interface
|
|
185
|
+
4. **Colocated fragments**: `.fragment.graphql` obok komponentu w `components/`
|
|
186
|
+
5. **Styling**: Uzywaj `cn()` dla laczenia klas Tailwind
|
|
187
|
+
6. **Obrazki**: next/image z alt i priority dla LCP
|
|
188
|
+
7. **Formularze**: Zod + react-hook-form
|
|
189
|
+
8. **Query keys**: Zawsze z `queryKeys.*` (nie hardcoded arrays)
|
|
190
|
+
9. **Config**: Zawsze z `graphqlConfig` (nie duplikuj env var resolution)
|
|
85
191
|
|
|
86
192
|
## GraphQL Operations
|
|
87
193
|
|
|
88
|
-
Operacje sa zdefiniowane w:
|
|
194
|
+
Operacje i schemat sa zdefiniowane w:
|
|
195
|
+
```
|
|
196
|
+
packages/@doswiftly/storefront-operations/
|
|
197
|
+
├── schema.graphql # Schemat GraphQL (zsynchronizowany z backendu)
|
|
198
|
+
├── queries.graphql # Zapytania
|
|
199
|
+
├── mutations.graphql # Mutacje
|
|
200
|
+
└── fragments.graphql # Fragmenty (backend SSOT)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Colocated component fragments:
|
|
89
204
|
```
|
|
90
|
-
|
|
91
|
-
├── queries.graphql
|
|
92
|
-
├── mutations.graphql
|
|
93
|
-
└── fragments.graphql
|
|
205
|
+
components/**/*.fragment.graphql # UI component fragments (Hydrogen/Relay pattern)
|
|
94
206
|
```
|
|
95
207
|
|
|
96
|
-
|
|
208
|
+
Codegen NIE wymaga uruchomionego backendu — schemat pochodzi z pliku.
|
|
209
|
+
Aby poznac dostepne operacje, przeczytaj pliki `.graphql` w storefront-operations.
|
|
@@ -1,194 +1,61 @@
|
|
|
1
|
-
# DoSwiftly Storefront
|
|
1
|
+
# DoSwiftly Storefront — shadcn/ui Template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Next.js 15+ storefront template with shadcn/ui, optimized for DoSwiftly Commerce.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Tech Stack
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- ✅ **GraphQL Codegen** for type-safe API calls
|
|
12
|
-
- ✅ **React Query** for data fetching
|
|
13
|
-
- ✅ **Zustand** for state management
|
|
14
|
-
- ✅ **Currency conversion** with client-side switching
|
|
7
|
+
- **Next.js 15+** with App Router and React Server Components
|
|
8
|
+
- **shadcn/ui** + Tailwind CSS v4
|
|
9
|
+
- **@doswiftly/storefront-sdk** — type-safe GraphQL hooks and Zustand stores
|
|
10
|
+
- **GraphQL Codegen** — auto-generated types from backend schema
|
|
15
11
|
|
|
16
12
|
## Getting Started
|
|
17
13
|
|
|
18
|
-
### 1. Install Dependencies
|
|
19
|
-
|
|
20
14
|
```bash
|
|
21
15
|
pnpm install
|
|
16
|
+
pnpm run codegen # Generate GraphQL types
|
|
17
|
+
pnpm run dev # http://localhost:3000
|
|
22
18
|
```
|
|
23
19
|
|
|
24
|
-
###
|
|
20
|
+
### Environment
|
|
25
21
|
|
|
26
|
-
Copy `.env.example` to `.env.local
|
|
22
|
+
Copy `.env.example` to `.env.local`:
|
|
27
23
|
|
|
28
24
|
```env
|
|
29
25
|
NEXT_PUBLIC_SHOP_SLUG=your-shop-slug
|
|
30
26
|
NEXT_PUBLIC_API_URL=https://api.doswiftly.pl
|
|
31
27
|
```
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Generate TypeScript types from your GraphQL schema:
|
|
29
|
+
## Project Structure
|
|
36
30
|
|
|
37
|
-
```bash
|
|
38
|
-
pnpm run codegen
|
|
39
31
|
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
app/ # Next.js App Router pages
|
|
33
|
+
components/
|
|
34
|
+
ui/ # shadcn/ui components
|
|
35
|
+
product/ # Product-related components
|
|
36
|
+
cart/ # Cart components
|
|
37
|
+
layout/ # Header, Footer, Navigation
|
|
38
|
+
providers/ # QueryProvider, CurrencyProvider
|
|
39
|
+
lib/
|
|
40
|
+
graphql/ # Server/client GraphQL helpers
|
|
41
|
+
stores/ # Zustand stores (cart, currency, auth)
|
|
42
|
+
generated/ # Auto-generated GraphQL types
|
|
45
43
|
```
|
|
46
44
|
|
|
47
|
-
Open [http://localhost:3000](http://localhost:3000) in your browser.
|
|
48
|
-
|
|
49
45
|
## Adding shadcn/ui Components
|
|
50
46
|
|
|
51
|
-
This template is pre-configured with shadcn/ui. Add components using the shadcn CLI:
|
|
52
|
-
|
|
53
47
|
```bash
|
|
54
|
-
# Add a button component
|
|
55
48
|
npx shadcn@latest add button
|
|
56
|
-
|
|
57
|
-
# Add a dialog component
|
|
58
49
|
npx shadcn@latest add dialog
|
|
59
|
-
|
|
60
|
-
# Add a dropdown menu
|
|
61
|
-
npx shadcn@latest add dropdown-menu
|
|
62
|
-
|
|
63
|
-
# See all available components
|
|
64
|
-
npx shadcn@latest add
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Components will be added to `components/ui/` directory.
|
|
68
|
-
|
|
69
|
-
## Project Structure
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
├── app/ # Next.js App Router pages
|
|
73
|
-
│ ├── layout.tsx # Root layout with providers
|
|
74
|
-
│ └── page.tsx # Homepage
|
|
75
|
-
├── components/
|
|
76
|
-
│ ├── ui/ # shadcn/ui components (auto-generated)
|
|
77
|
-
│ ├── layout/ # Layout components (Header, Footer)
|
|
78
|
-
│ └── providers/ # React providers (Query, Currency)
|
|
79
|
-
├── lib/
|
|
80
|
-
│ ├── graphql/
|
|
81
|
-
│ │ ├── server.ts # Server-side GraphQL client
|
|
82
|
-
│ │ ├── client.ts # Client-side GraphQL client
|
|
83
|
-
│ │ └── hooks.ts # React Query hooks
|
|
84
|
-
│ └── utils.ts # Utility functions (cn helper)
|
|
85
|
-
├── stores/
|
|
86
|
-
│ └── currency-store.ts # Zustand currency store
|
|
87
|
-
├── generated/
|
|
88
|
-
│ └── graphql.ts # Auto-generated GraphQL types
|
|
89
|
-
├── doswiftly.config.ts # DoSwiftly configuration
|
|
90
|
-
├── components.json # shadcn/ui configuration
|
|
91
|
-
└── codegen.ts # GraphQL Codegen configuration
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## GraphQL Codegen
|
|
95
|
-
|
|
96
|
-
This template uses GraphQL Codegen to generate TypeScript types from your GraphQL schema.
|
|
97
|
-
|
|
98
|
-
### Configuration
|
|
99
|
-
|
|
100
|
-
See `codegen.ts` for configuration. It reads:
|
|
101
|
-
- **Schema**: From your DoSwiftly API
|
|
102
|
-
- **Operations**: From `@doswiftly/storefront-operations` package
|
|
103
|
-
- **Custom queries**: From `src/graphql/**/*.{ts,tsx}`
|
|
104
|
-
|
|
105
|
-
### Running Codegen
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
# Generate types
|
|
109
|
-
pnpm run codegen
|
|
110
|
-
|
|
111
|
-
# Watch mode (auto-regenerate on changes)
|
|
112
|
-
pnpm run codegen:watch
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Currency Management
|
|
116
|
-
|
|
117
|
-
This template includes built-in currency conversion:
|
|
118
|
-
|
|
119
|
-
1. **Server Components**: Render prices in base currency (SSG-compatible)
|
|
120
|
-
2. **Client Components**: Switch to user's preferred currency dynamically
|
|
121
|
-
3. **Currency Store**: Persists user preference in localStorage
|
|
122
|
-
|
|
123
|
-
### Usage
|
|
124
|
-
|
|
125
|
-
```tsx
|
|
126
|
-
// Server Component
|
|
127
|
-
import { fetchProduct } from '@/lib/graphql/server';
|
|
128
|
-
|
|
129
|
-
export default async function ProductPage({ params }) {
|
|
130
|
-
const { product } = await fetchProduct(params.handle);
|
|
131
|
-
// Prices in base currency
|
|
132
|
-
return <div>{product.priceRange.minVariantPrice.amount}</div>;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Client Component
|
|
136
|
-
'use client';
|
|
137
|
-
import { useProduct } from '@/lib/graphql/hooks';
|
|
138
|
-
import { useCurrencyStore } from '@/stores/currency-store';
|
|
139
|
-
|
|
140
|
-
export function ProductPrice({ handle }) {
|
|
141
|
-
const currency = useCurrencyStore((s) => s.currency);
|
|
142
|
-
const { data } = useProduct(handle);
|
|
143
|
-
// Prices in user's preferred currency
|
|
144
|
-
return <div>{data.product.priceRange.minVariantPrice.amount} {currency}</div>;
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## Styling
|
|
149
|
-
|
|
150
|
-
This template uses Tailwind CSS v4 with shadcn/ui.
|
|
151
|
-
|
|
152
|
-
### Customizing Theme
|
|
153
|
-
|
|
154
|
-
Edit `app/globals.css` to customize colors:
|
|
155
|
-
|
|
156
|
-
```css
|
|
157
|
-
@layer base {
|
|
158
|
-
:root {
|
|
159
|
-
--background: 0 0% 100%;
|
|
160
|
-
--foreground: 222.2 84% 4.9%;
|
|
161
|
-
/* ... more variables */
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Using cn() Helper
|
|
167
|
-
|
|
168
|
-
The `cn()` helper combines Tailwind classes with proper precedence:
|
|
169
|
-
|
|
170
|
-
```tsx
|
|
171
|
-
import { cn } from '@/lib/utils';
|
|
172
|
-
|
|
173
|
-
<div className={cn('text-base', isActive && 'text-primary')} />
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Building for Production
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
# Build
|
|
180
|
-
pnpm run build
|
|
181
|
-
|
|
182
|
-
# Start production server
|
|
183
|
-
pnpm run start
|
|
184
50
|
```
|
|
185
51
|
|
|
186
|
-
##
|
|
52
|
+
## Documentation
|
|
187
53
|
|
|
188
|
-
- [
|
|
189
|
-
- [
|
|
190
|
-
- [
|
|
191
|
-
- [
|
|
54
|
+
- [SDK Overview](https://docs.doswiftly.pl/storefront-developer/sdk/overview) — hooks, stores, architecture
|
|
55
|
+
- [SDK Products](https://docs.doswiftly.pl/storefront-developer/sdk/products) — product queries and mutations
|
|
56
|
+
- [API Queries](https://docs.doswiftly.pl/storefront-developer/api/queries) — available GraphQL queries
|
|
57
|
+
- [API Mutations](https://docs.doswiftly.pl/storefront-developer/api/mutations) — available GraphQL mutations
|
|
58
|
+
- [CLI Commands](https://docs.doswiftly.pl/storefront-developer/cli-commands) — full CLI reference
|
|
192
59
|
|
|
193
60
|
## License
|
|
194
61
|
|