@doswiftly/cli 0.1.19 → 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 (147) hide show
  1. package/dist/commands/deploy.d.ts +20 -0
  2. package/dist/commands/deploy.d.ts.map +1 -1
  3. package/dist/commands/deploy.js +219 -6
  4. package/dist/commands/deploy.js.map +1 -1
  5. package/package.json +4 -4
  6. package/templates/storefront-minimal/.github/workflows/build-template.yml +10 -0
  7. package/templates/storefront-minimal/wrangler.toml +11 -0
  8. package/templates/storefront-nextjs/.github/workflows/build-template.yml +10 -0
  9. package/templates/storefront-nextjs/wrangler.toml +11 -0
  10. package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +10 -0
  11. package/templates/storefront-nextjs-shadcn/CLAUDE.md +29 -5
  12. package/templates/storefront-nextjs-shadcn/app/{about → [locale]/about}/page.tsx +17 -14
  13. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/addresses/page.tsx +19 -15
  14. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/error.tsx +8 -5
  15. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loyalty/page.tsx +39 -34
  16. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/page.tsx +9 -7
  17. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/tracking/page.tsx +27 -25
  18. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/page.tsx +13 -9
  19. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/page.tsx +1 -2
  20. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/settings/page.tsx +1 -1
  21. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx +14 -12
  22. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/login/page.tsx +5 -2
  23. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/register/page.tsx +5 -2
  24. package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/page.tsx +1 -1
  25. package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/page.tsx +14 -10
  26. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/[slug]/category-products-client.tsx +4 -2
  27. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/page.tsx +13 -8
  28. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/error.tsx +1 -1
  29. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/page.tsx +228 -184
  30. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/success/[orderId]/page.tsx +36 -34
  31. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/page.tsx +5 -3
  32. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/page.tsx +13 -8
  33. package/templates/storefront-nextjs-shadcn/app/{contact → [locale]/contact}/page.tsx +24 -21
  34. package/templates/storefront-nextjs-shadcn/app/{error.tsx → [locale]/error.tsx} +13 -8
  35. package/templates/storefront-nextjs-shadcn/app/[locale]/layout.tsx +92 -0
  36. package/templates/storefront-nextjs-shadcn/app/{not-found.tsx → [locale]/not-found.tsx} +13 -18
  37. package/templates/storefront-nextjs-shadcn/app/{page.tsx → [locale]/page.tsx} +8 -4
  38. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/error.tsx +1 -1
  39. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/page.tsx +11 -8
  40. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/product-client.tsx +3 -1
  41. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/page.tsx +6 -3
  42. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/products-client.tsx +14 -10
  43. package/templates/storefront-nextjs-shadcn/app/{wishlist → [locale]/wishlist}/page.tsx +21 -25
  44. package/templates/storefront-nextjs-shadcn/app/layout.tsx +6 -68
  45. package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +25 -20
  46. package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +11 -10
  47. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +14 -12
  48. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +28 -18
  49. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +10 -8
  50. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +27 -22
  51. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +48 -43
  52. package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +1 -1
  53. package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +1 -1
  54. package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +1 -1
  55. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +7 -4
  56. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +1 -1
  57. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +7 -5
  58. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +9 -7
  59. package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +8 -5
  60. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +18 -15
  61. package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +15 -25
  62. package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +10 -8
  63. package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +9 -6
  64. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +5 -3
  65. package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +8 -5
  66. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +5 -3
  67. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +8 -7
  68. package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +1 -1
  69. package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +1 -1
  70. package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +9 -6
  71. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +21 -11
  72. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +16 -13
  73. package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +53 -28
  74. package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +7 -5
  75. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +19 -15
  76. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +12 -9
  77. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +8 -5
  78. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +1 -1
  79. package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +12 -8
  80. package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +13 -8
  81. package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +10 -8
  82. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +37 -12
  83. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +5 -2
  84. package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +24 -23
  85. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +20 -12
  86. package/templates/storefront-nextjs-shadcn/components/layout/language-switcher.tsx +54 -0
  87. package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +33 -30
  88. package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +27 -24
  89. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +23 -24
  90. package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +6 -14
  91. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +1 -1
  92. package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +4 -1
  93. package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +7 -4
  94. package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +5 -3
  95. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +8 -6
  96. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +3 -1
  97. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +3 -7
  98. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +26 -13
  99. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +25 -27
  100. package/templates/storefront-nextjs-shadcn/components/providers/language-sync-provider.tsx +27 -0
  101. package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +40 -7
  102. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +56 -70
  103. package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +7 -4
  104. package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +12 -9
  105. package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +23 -12
  106. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +7 -4
  107. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +1 -1
  108. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +2 -10
  109. package/templates/storefront-nextjs-shadcn/generated/graphql.ts +1159 -551
  110. package/templates/storefront-nextjs-shadcn/hooks/index.ts +1 -0
  111. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +22 -249
  112. package/templates/storefront-nextjs-shadcn/hooks/use-cart-di.ts +67 -0
  113. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +3 -3
  114. package/templates/storefront-nextjs-shadcn/i18n/navigation.ts +12 -0
  115. package/templates/storefront-nextjs-shadcn/i18n/request.ts +17 -0
  116. package/templates/storefront-nextjs-shadcn/i18n/routing.ts +17 -0
  117. package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +1 -0
  118. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +41 -8
  119. package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +20 -18
  120. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +2 -1
  121. package/templates/storefront-nextjs-shadcn/messages/en.json +869 -0
  122. package/templates/storefront-nextjs-shadcn/messages/pl.json +869 -0
  123. package/templates/storefront-nextjs-shadcn/next.config.ts +6 -5
  124. package/templates/storefront-nextjs-shadcn/package.json +3 -2
  125. package/templates/storefront-nextjs-shadcn/proxy.ts +115 -46
  126. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +24 -58
  127. package/templates/storefront-nextjs-shadcn/wrangler.toml +11 -0
  128. /package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loading.tsx +0 -0
  129. /package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/loading.tsx +0 -0
  130. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/loading.tsx +0 -0
  131. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/loading.tsx +0 -0
  132. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/page.tsx +0 -0
  133. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/[slug]/page.tsx +0 -0
  134. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/page.tsx +0 -0
  135. /package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/loading.tsx +0 -0
  136. /package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/[slug]/loading.tsx +0 -0
  137. /package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/[slug]/page.tsx +0 -0
  138. /package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/loading.tsx +0 -0
  139. /package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/loading.tsx +0 -0
  140. /package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/loading.tsx +0 -0
  141. /package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/loading.tsx +0 -0
  142. /package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/loading.tsx +0 -0
  143. /package/templates/storefront-nextjs-shadcn/app/{returns → [locale]/returns}/page.tsx +0 -0
  144. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/loading.tsx +0 -0
  145. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/page.tsx +0 -0
  146. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/search-client.tsx +0 -0
  147. /package/templates/storefront-nextjs-shadcn/app/{shipping → [locale]/shipping}/page.tsx +0 -0
@@ -1,10 +1,14 @@
1
1
  import type { NextConfig } from 'next';
2
+ import createNextIntlPlugin from 'next-intl/plugin';
3
+
4
+ const withNextIntl = createNextIntlPlugin();
2
5
 
3
6
  const nextConfig: NextConfig = {
4
7
  // Enable React strict mode for better development experience
5
8
  reactStrictMode: true,
6
9
 
7
- // Image optimization configuration
10
+ // Image optimization — GraphQL API returns ready-to-use CDN URLs.
11
+ // Use url(transform: { maxWidth: 800 }) in queries. No client-side loader needed.
8
12
  images: {
9
13
  remotePatterns: [
10
14
  {
@@ -21,11 +25,8 @@ const nextConfig: NextConfig = {
21
25
  port: '8000',
22
26
  },
23
27
  ],
24
- // Allow dangerous URLs for local development
25
28
  dangerouslyAllowSVG: true,
26
29
  contentDispositionType: 'attachment',
27
- // Disable image optimization for local development if needed
28
- unoptimized: process.env.NODE_ENV === 'development',
29
30
  },
30
31
 
31
32
  // Experimental features
@@ -44,4 +45,4 @@ const nextConfig: NextConfig = {
44
45
  },
45
46
  };
46
47
 
47
- export default nextConfig;
48
+ export default withNextIntl(nextConfig);
@@ -15,7 +15,7 @@
15
15
  "@doswiftly/storefront-operations": "{{STOREFRONT_OPS_VERSION}}",
16
16
  "@doswiftly/storefront-sdk": "^4.0.0",
17
17
  "@tanstack/react-query": "^5.62.0",
18
- "next": "^16.0.0",
18
+ "next": "^16.1.7",
19
19
  "react": "^19",
20
20
  "react-dom": "^19",
21
21
  "lucide-react": "latest",
@@ -34,6 +34,7 @@
34
34
  "zustand": "^5.0.2",
35
35
  "zod": "^3.23.8",
36
36
  "sonner": "^1.7.1",
37
+ "next-intl": "^4.1.0",
37
38
  "next-themes": "^0.4.4",
38
39
  "react-hook-form": "^7.55.0",
39
40
  "@hookform/resolvers": "^5.2.0"
@@ -44,7 +45,7 @@
44
45
  "@graphql-typed-document-node/core": "^3.2.0",
45
46
  "graphql": "^16.10.0",
46
47
  "@next/env": "^16.0.0",
47
- "@opennextjs/cloudflare": "^1.0.0",
48
+ "@opennextjs/cloudflare": "^1.17.1",
48
49
  "@types/node": "latest",
49
50
  "@types/react": "latest",
50
51
  "@types/react-dom": "latest",
@@ -1,79 +1,148 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import type { NextRequest } from "next/server";
3
- import { AUTH_COOKIE_NAME, matchesRoute } from "@doswiftly/storefront-sdk";
3
+ import createMiddleware from "next-intl/middleware";
4
+ import { defaultLocale, localePrefix } from "@/i18n/routing";
5
+ import {
6
+ AUTH_COOKIE_NAME,
7
+ LANGUAGE_COOKIE_NAME,
8
+ LANGUAGE_COOKIE_MAX_AGE,
9
+ matchesRoute,
10
+ } from "@doswiftly/storefront-sdk";
4
11
  import {
5
12
  protectedRoutes,
6
13
  guestOnlyRoutes,
7
14
  redirects,
8
15
  } from "@/lib/auth/routes";
9
16
 
17
+ const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";
18
+ const shopSlug = process.env.NEXT_PUBLIC_SHOP_SLUG || "demo-shop";
19
+
10
20
  /**
11
- * Authentication Proxy Function (Next.js 16+)
12
- *
13
- * Security Model (3 layers):
14
- * 1. Proxy function (this file) - Fast redirect based on cookie existence (UX layer)
15
- * 2. AuthGuard component - Client-side validation via useAuth hook
16
- * 3. GraphQL Backend - Ultimate security (validates token on every request)
17
- *
18
- * IMPORTANT: This proxy checks cookie EXISTENCE, not VALIDITY.
19
- * Token validation happens in:
20
- * - AuthGuard (client-side via useAuth hook)
21
- * - GraphQL API (server-side, ultimate security)
21
+ * Fetch supported locales from backend (cached 60s).
22
+ * Backend is SSOT — merchant adds/removes language → immediately reflected.
22
23
  *
23
- * Why this approach?
24
- * - Proxy runs on Edge Runtime (fast, but limited capabilities)
25
- * - Cannot make GraphQL requests to validate token
26
- * - Provides instant redirect without waiting for client hydration
27
- * - Prevents flash of protected content for unauthenticated users
28
- *
29
- * @see lib/auth/routes.ts - SSOT for route configuration
30
- * @see components/auth/auth-guard.tsx - Client-side auth protection
24
+ * In-memory cache is acceptable in middleware context — warm instances benefit,
25
+ * cold starts make one extra backend call (graceful degradation).
31
26
  */
32
- export function proxy(request: NextRequest) {
27
+ let cachedLocales: string[] | null = null;
28
+ let cacheExpiry = 0;
29
+ let cachedIntlMiddleware: ReturnType<typeof createMiddleware> | null = null;
30
+ let cachedLocaleRegex: RegExp | null = null;
31
+
32
+ async function getSupportedLocales(): Promise<string[]> {
33
+ const now = Date.now();
34
+ if (cachedLocales && now < cacheExpiry) {
35
+ return cachedLocales;
36
+ }
37
+
38
+ try {
39
+ const res = await fetch(`${apiUrl}/storefront/graphql`, {
40
+ method: "POST",
41
+ headers: {
42
+ "Content-Type": "application/json",
43
+ "X-Shop-Slug": shopSlug,
44
+ },
45
+ body: JSON.stringify({
46
+ query: `{ shop { supportedLanguages } }`,
47
+ }),
48
+ });
49
+ const json = await res.json();
50
+ const locales: string[] =
51
+ json?.data?.shop?.supportedLanguages?.filter(Boolean);
52
+
53
+ if (locales && locales.length > 0) {
54
+ cachedLocales = locales;
55
+ cacheExpiry = now + 60_000; // 60s cache
56
+ // Rebuild derived caches when locales change
57
+ cachedIntlMiddleware = createMiddleware({
58
+ locales,
59
+ defaultLocale,
60
+ localePrefix,
61
+ localeCookie: {
62
+ name: LANGUAGE_COOKIE_NAME,
63
+ maxAge: LANGUAGE_COOKIE_MAX_AGE,
64
+ },
65
+ });
66
+ cachedLocaleRegex = new RegExp(
67
+ `^\\/(${locales.join("|")})(\\\/|$)`
68
+ );
69
+ return locales;
70
+ }
71
+ } catch {
72
+ // Backend unreachable — use cached or fallback
73
+ }
74
+
75
+ return cachedLocales || [defaultLocale];
76
+ }
77
+
78
+ function getIntlMiddleware(locales: string[]) {
79
+ if (cachedIntlMiddleware) return cachedIntlMiddleware;
80
+ cachedIntlMiddleware = createMiddleware({
81
+ locales,
82
+ defaultLocale,
83
+ localePrefix,
84
+ localeCookie: {
85
+ name: LANGUAGE_COOKIE_NAME,
86
+ maxAge: LANGUAGE_COOKIE_MAX_AGE,
87
+ },
88
+ });
89
+ return cachedIntlMiddleware;
90
+ }
91
+
92
+ function getLocaleRegex(locales: string[]) {
93
+ if (cachedLocaleRegex) return cachedLocaleRegex;
94
+ cachedLocaleRegex = new RegExp(`^\\/(${locales.join("|")})(\\\/|$)`);
95
+ return cachedLocaleRegex;
96
+ }
97
+
98
+ export async function proxy(request: NextRequest) {
99
+ // Step 1: Get dynamic locales from backend
100
+ const locales = await getSupportedLocales();
101
+
102
+ // Step 2: next-intl locale detection & routing (cached middleware instance)
103
+ const handleI18nRouting = getIntlMiddleware(locales);
104
+ const response = handleI18nRouting(request);
105
+
106
+ // Step 3: Auth checks
33
107
  const { pathname } = request.nextUrl;
34
108
  const token = request.cookies.get(AUTH_COOKIE_NAME)?.value;
35
109
  const hasToken = Boolean(token);
36
110
 
37
- // Protected routes - redirect to login if no token
38
- if (matchesRoute(pathname, protectedRoutes)) {
111
+ // Strip locale prefix for route matching (cached regex)
112
+ const localePattern = getLocaleRegex(locales);
113
+ const localeMatch = pathname.match(localePattern);
114
+ const urlLocalePrefix = localeMatch ? `/${localeMatch[1]}` : "";
115
+ const pathnameWithoutLocale = pathname.replace(localePattern, "/");
116
+ const matchPathname =
117
+ pathnameWithoutLocale === "" ? "/" : pathnameWithoutLocale;
118
+
119
+ if (matchesRoute(matchPathname, protectedRoutes)) {
39
120
  if (!hasToken) {
40
- const loginUrl = new URL(redirects.unauthenticated, request.url);
41
- // Preserve the original URL for redirect after login
121
+ const loginUrl = new URL(
122
+ `${urlLocalePrefix}${redirects.unauthenticated}`,
123
+ request.url
124
+ );
42
125
  loginUrl.searchParams.set("redirect", pathname);
43
126
  return NextResponse.redirect(loginUrl);
44
127
  }
45
128
  }
46
129
 
47
- // Guest-only routes - redirect to account if has token
48
- if (matchesRoute(pathname, guestOnlyRoutes)) {
130
+ if (matchesRoute(matchPathname, guestOnlyRoutes)) {
49
131
  if (hasToken) {
50
132
  return NextResponse.redirect(
51
- new URL(redirects.authenticated, request.url)
133
+ new URL(
134
+ `${urlLocalePrefix}${redirects.authenticated}`,
135
+ request.url
136
+ )
52
137
  );
53
138
  }
54
139
  }
55
140
 
56
- return NextResponse.next();
141
+ return response;
57
142
  }
58
143
 
59
- /**
60
- * Matcher configuration
61
- *
62
- * Only run proxy on routes that need auth checks.
63
- * This improves performance by skipping static assets, API routes, etc.
64
- *
65
- * Update this when adding new protected or guest-only route groups.
66
- */
67
144
  export const config = {
68
145
  matcher: [
69
- /*
70
- * Match all request paths except:
71
- * - _next/static (static files)
72
- * - _next/image (image optimization files)
73
- * - favicon.ico (favicon file)
74
- * - public folder files (images, etc.)
75
- * - API routes (handled separately)
76
- */
77
- "/((?!_next/static|_next/image|favicon.ico|.*\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
146
+ "/((?!api|trpc|_next|_vercel|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico)$).*)",
78
147
  ],
79
148
  };
@@ -1,58 +1,24 @@
1
- import { createStore } from 'zustand/vanilla';
2
- import { persist } from 'zustand/middleware';
3
- import { createStoreContext } from '@doswiftly/storefront-sdk/react';
4
-
5
- export interface CartState {
6
- // State
7
- cartId: string | null;
8
- isOpen: boolean;
9
-
10
- // Actions
11
- setCartId: (cartId: string | null) => void;
12
- clearCart: () => void;
13
- openCart: () => void;
14
- closeCart: () => void;
15
- toggleCart: () => void;
16
- }
17
-
18
- export function createCartStore() {
19
- return createStore<CartState>()(
20
- persist(
21
- (set) => ({
22
- cartId: null,
23
- isOpen: false,
24
-
25
- setCartId: (cartId: string | null) => {
26
- set({ cartId });
27
- },
28
-
29
- clearCart: () => {
30
- set({ cartId: null, isOpen: false });
31
- },
32
-
33
- openCart: () => {
34
- set({ isOpen: true });
35
- },
36
-
37
- closeCart: () => {
38
- set({ isOpen: false });
39
- },
40
-
41
- toggleCart: () => {
42
- set((state) => ({ isOpen: !state.isOpen }));
43
- },
44
- }),
45
- {
46
- name: 'cart-storage',
47
- // Persist only cartId — server is the source of truth for items
48
- partialize: (state) => ({ cartId: state.cartId }),
49
- },
50
- ),
51
- );
52
- }
53
-
54
- export const {
55
- Provider: CartProvider,
56
- useStore: useCartStore,
57
- useApi: useCartStoreApi,
58
- } = createStoreContext<CartState>('CartStore');
1
+ /**
2
+ * Cart store — re-export facade from SDK.
3
+ *
4
+ * All cart state management is now in @doswiftly/storefront-sdk/react.
5
+ * This file preserves import compatibility for existing template consumers.
6
+ */
7
+ export {
8
+ createCartStore,
9
+ CartProvider,
10
+ useCartStore,
11
+ useCartStoreApi,
12
+ selectCartId,
13
+ selectIsCartOpen,
14
+ selectCartIsLoading,
15
+ } from '@doswiftly/storefront-sdk/react';
16
+
17
+ export type {
18
+ CartState,
19
+ CartActions,
20
+ CartStoreConfig,
21
+ CartData,
22
+ CartLineInput,
23
+ CartLineUpdateInput,
24
+ } from '@doswiftly/storefront-sdk/react';
@@ -11,3 +11,14 @@ assets = { directory = ".open-next/assets", binding = "ASSETS" }
11
11
  # Cloudflare Images binding for Next.js /_next/image optimization
12
12
  [images]
13
13
  binding = "IMAGES"
14
+
15
+ # Observability — logs persisted in Cloudflare Dashboard
16
+ [observability]
17
+ enabled = true
18
+ head_sampling_rate = 1
19
+
20
+ [observability.logs]
21
+ enabled = true
22
+ head_sampling_rate = 1
23
+ persist = true
24
+ invocation_logs = true